Dicas para obter entrega "contínua"

14

Uma equipe está enfrentando dificuldades para liberar software com frequência (uma vez por semana). O que se segue é uma linha do tempo de lançamento típica:

Durante a iteração:

  • Os desenvolvedores trabalham em histórias na lista de pendências em ramos de recursos de curta duração (isso é aplicado com entusiasmo) com base no ramo mestre.
  • Os desenvolvedores costumam puxar suas ramificações de recursos para a ramificação de integração, que é continuamente criada e testada (no que diz respeito à cobertura do teste) automaticamente.
  • Os testadores têm a capacidade de implantar automaticamente a integração em um ambiente de teste e isso ocorre várias vezes por semana, permitindo a execução contínua de seus conjuntos de testes.

Toda segunda-feira:

  • há uma reunião de planejamento de lançamento para determinar quais histórias são "conhecidas" (com base no trabalho dos testadores) e, portanto, estarão no lançamento. Se houver um problema conhecido em uma história, o ramo de origem será retirado da integração.
  • nenhum código novo (apenas correções de erros solicitadas pelos testadores) poderá ser incluído na integração nesta segunda-feira para garantir que os testadores tenham uma base de código estável para cortar uma versão.

Toda terça:

  • Os testadores testaram o ramo de integração o máximo possível e forneceram o tempo disponível e não há bugs conhecidos; portanto, uma liberação é cortada e enviada aos nós de produção lentamente.

Isso parece bom na prática, mas descobrimos que é incrivelmente difícil de alcançar. A equipe vê os seguintes sintomas

  • erros "sutis" são encontrados na produção que não foram identificados no ambiente de preparação.
  • as correções de última hora continuam na terça-feira.
  • problemas no ambiente de produção exigem reversões que bloqueiam o desenvolvimento contínuo até que uma implantação ativa seja bem-sucedida e a ramificação principal possa ser atualizada (e, portanto, ramificada).

Acho que a cobertura do teste, a qualidade do código, a capacidade de regressar rapidamente, as alterações de última hora e as diferenças ambientais estão em jogo aqui. Alguém pode oferecer algum conselho sobre a melhor forma de obter uma entrega "contínua"?

Ben
fonte
1
Na sequência da resposta de @ emddudley sobre o livro Entrega Contínua , incentivamos você a assistir a infoq.com/presentations/Continuous-Deployment-50-Times-a-Day uma apresentação realmente interessante sobre a verdadeira implantação de várias vezes ao dia na exibição ao vivo real Produção.
Sdg

Respostas:

6
  • bugs "sutis" são encontrados na produção que não foram identificados no ambiente de preparação - em um dos projetos com esses problemas que vi, isso foi resolvido com êxito pela tática que eu chamaria de problemas duplos. Quero dizer, para erros como esse, os caras criaram dois tickets no rastreador de problemas: um foi atribuído aos desenvolvedores para corrigir o código, outro aos testadores para projetar e estabelecer teste de regressão ou alteração no ambiente de teste que impediria repeti-lo no futuro. Isso ajudou a manter a encenação perto o suficiente para estimular.

  • problemas no ambiente de produção exigem reversões - se forem frequentes, os lançamentos semanais são realmente falsos - considere ajustar a frequência ao nível que realmente funciona. Por falso, quero dizer que, se digamos um dos dois lançamentos semanais de lançamentos, isso significa que os usuários enfrentam novos lançamentos (trabalhando) uma vez a cada duas semanas - o que é tudo o que importa, não o número de vezes que você implanta.

  • ramos de recursos aplicados com entusiasmo - isso significa que, algum tempo antes, você também tentou trabalhar no ramo único e o achou inferior? Se sim, pule o resto. Caso contrário, tente trabalhar na ramificação única (se necessário, pesquise no Google a estratégia de ramificação "ramificação de desenvolvimento" ou a estratégia de ramificação "tronco instável" para obter detalhes). Ou, se você usa o Perforce, pesquise na Web as diretrizes da Microsoft sobre ramificação e mesclagem. Tente eu disse isso? desculpe, a palavra apropriada deve ser testada : quero dizer, 1) planeje quando e como medir se um único ramo é melhor ou não do que o que você tem agora e 2) planeje quando e como você voltará para os ramos do recurso, caso isso teste falha .


PS.

Provavelmente você pode encontrar mais truques assim pesquisando na Web algo como gerenciamento de riscos de projetos de software


atualizar

<copiar dos comentários>

Percebo que as correções frequentes são um sintoma de um pipeline de testes quebrado - não é esse o caso? De qualquer forma, eles exigem lançamentos repetidos para obter os hot fixs, dando mais trabalho à equipe de operações. Além disso, os hot fixes são geralmente codificados sob pressão de tempo extrema, o que significa que provavelmente terão qualidade inferior ao trabalho normal.

</ copiar dos comentários>

  • correções de última hora - as preocupações acima parecem razoáveis ​​para mim, assim como sua referência ao pipeline de teste quebrado. Com esta atualização, sua observação anterior de que a nova integração de código está bloqueada na segunda-feira parece mais um sintoma de um pipeline quebrado (acho que uma palavra mais precisa seria contestada ). Por contenção, quero dizer o seguinte: você usa uma única ramificação para servir simultaneamente a dois propósitos: integração e liberação. Quando a liberação se aproxima, esses dois propósitos começam a colidir entre si, pressionando por requisitos conflitantes: o objetivo da integração é melhor atendido com ramificação continuamente aberta ( Mesclar cedo e frequentemente ), enquanto a estabilidade da liberação se beneficia com a vedação da ramificação(isolado) o maior tempo possível. A-ha, parece que as peças do quebra-cabeça começam a ser combinadas ...

.. Olha, esse congelamento de segunda-feira agora parece um compromisso feito para servir a propósitos conflitantes: os desenvolvedores sofrem com o bloco de integração de novos códigos, enquanto os testadores sofrem com esse bloco sendo muito breve, todo mundo está um pouco infeliz, mas ambos os propósitos são mais ou menos atendidos.

Você sabe, dado acima, acho que sua melhor aposta seria tentar liberar do ramo dedicado (além da integração) . Se esse ramo terá vida longa como integração ou terá vida curta como os ramos de seu recurso (com "recurso" sendo, bem, liberado)) - depende de você, só precisa ser separado.

Apenas pense nisso. Atualmente, você acha que um dia não é suficiente para estabilizar convenientemente o lançamento, certo? com a nova estratégia de ramificação, você pode apenas bifurcar 2 dias antes do lançamento em vez de um, sem problemas. Se você achar que até dois dias não são suficientes, tente forçar três dias antes, etc. O problema é que você pode isolar a ramificação de liberação o quanto antes, pois isso não impedirá mais a fusão de novo código na ramificação de integração. Observe neste modelo que não há necessidade de congelar a ramificação de integração - seus desenvolvedores podem usá-la continuamente , na segunda, terça, sexta-feira, qualquer que seja.

O preço pago por essa felicidade é uma complicação dos hotfixes. Eles precisariam ser mesclados em duas ramificações, em vez de uma (liberação + integração). É nisso que você deve se concentrar ao testar o novo modelo. Acompanhe tudo o que está relacionado - esforço extra que você gasta na fusão com a segunda ramificação, esforços relacionados ao risco de esquecer a fusão com a segunda ramificação - tudo relacionado.

No final do teste, apenas agregue o que você acompanhou e saiba se essa quantidade de esforço extra é aceitável ou não. Se for aceitável, você está pronto. Caso contrário, volte ao seu modelo atual, analise o que deu errado e comece a pensar em como mais você pode melhorar.


update2

<copiar dos comentários>

Meu objetivo é fazer com que as histórias sejam testadas e entregues (atrás ou na frente de uma parede de configuração) dentro de uma iteração, isso só pode ser alcançado se os testadores estiverem testando o trabalho realizado na iteração (e não estabilizando o código da iteração anterior).

</ copiar dos comentários>

Entendo. Bem, eu não tenho experiência direta com esse caminho, mas vi testes de tipo de iteração realizados com sucesso em um projeto relacionado ao nosso. Como nosso projeto estava seguindo o caminho oposto, também tive o luxo de comparar pessoalmente essas abordagens opostas .

Na minha perspectiva, a abordagem de teste fora de iteração parecia superior nessa corrida. Sim, o projeto deles correu bem e os testadores detectaram erros mais rapidamente que o nosso, mas de alguma forma isso não ajudou. Nosso projeto também correu bem e, de alguma forma, podíamos oferecer iterações mais curtas do que eles, e tivemos menos (muito menos) lançamentos escorregadios do que eles, e havia menos tensão entre os desenvolvedores e os testadores ao nosso lado.

BTW, apesar da detecção mais rápida do lado deles, conseguimos ter a mesma vida útil média do bug (o tempo de vida é o tempo entre a introdução e a correção , e não entre a introdução e a detecção). Provavelmente até tivemos uma ligeira vantagem aqui, pois com iterações mais curtas e menos lançamentos escorregadios, poderíamos afirmar que, em média, nossas correções atingem os usuários mais rapidamente que os deles.

Resumindo, ainda acredito que o isolamento da linha de código de lançamento tem melhores chances de melhorar a produtividade da sua equipe.


em uma reflexão mais aprofundada ...

  • o isolamento da linha de código de liberação tem melhores chances - ao reler, sinto que isso pode causar uma impressão de desencorajá-lo a tentar o teste na iteração . Eu gostaria de deixar perfeitamente claro que não.

No seu caso, a abordagem de teste em iteração parece segura de tentar (er ... test ) porque você parece ter uma compreensão clara de como alcançá-la ( fluxo de teste suave ) e quais são os principais obstáculos. Afinal, você sempre tem a opção de recorrer a uma abordagem alternativa, se achar muito difícil obter esse pipeline correto.

No que diz respeito a obstáculos, outros que valem a pena acompanhar nesse caso serão problemas como falha na reprodução de bugs no lado do desenvolvedor e atraso na localização / atraso na verificação da correção no lado dos testadores. Isso também pode atrapalhar seu pipeline , como acontece agora com os hotfixes.

mosquito
fonte
1
Obrigado por suas idéias. Em relação à ramificação, testamos um não. de abordagens (e, de fato, usei várias organizações diferentes em minha carreira). Decidimos um mestre limpo que representa o código de produção, um ramo de integração (baseado no mestre) em que todos os desenvolvedores acessam frequentemente (várias vezes ao dia, idealmente). O ramo de integração é construído e testado continuamente, com implantações de teste automatizadas frequentes. Eu tentei mainline sujo com grande sucesso antes. Nossa abordagem atual parece mais controlada. Usamos paredes de configuração para funcionalidades incompletas e indesejadas.
Ben
1
@maple_shaft bem, a primeira vez que vi bugs abertos no rastreador contra a suíte de testes foi em 2002 ou 2003. E parecia ser uma prática bastante estabelecida na equipe em que entrei na época. Quanto aos erros visando diffs entre prod e estadiamento, estes fato parece novela para mim desde a primeira vez que eu vi ele (e foi realmente surpreendidos) foi inferior a 2 anos
mosquito
1
@gnat, Parece senso comum e é por isso que me pergunto por que não ouvi isso antes. Agora que penso nisso, faz sentido, porque todos os grupos de controle de qualidade com os quais trabalhei pareciam perfeitamente felizes em exibir bugs, mas tornaram-se reluzentes aos dois anos de idade sempre que os bugs eram trazidos contra eles.
maple_shaft
1
@maple_shaft lol concorda que este caminho parece ser imerecidamente raro. Você sabia pela maneira como se pode lançar bugs não apenas nos testadores, mas também nos escritores de documentos / especificações? - O Build 12 do Dev Guide diz "black" na página 34, linha 5; deve ser "branco". - Atribuído para John Writer. - Corrigido na compilação 67. - Correção verificada na compilação 89 por Paul Tester.
Gnat
1
Minha última resposta, como não quero me transformar em uma sessão de bate-papo, mas na minha última organização, escrevi um bug contra um escritor de especificações e toda a divisão recuou em um momento da WTF. Foi-me dito prontamente que eu tinha um "problema de atitude" e que eu não era um "jogador da equipe" e não o faria novamente.
maple_shaft
8

Sem saber a natureza das histórias de usuários e o número delas, devo dizer que um ciclo de lançamento de uma semana parece extremo. O cenário acima descrito é intricadamente planejado e envolve uma série de diferentes ramificações, pontos de mesclagem, transferências, ambientes e suítes de teste, criando mais ou menos um sistema humano em que um único erro em meio à complexidade do plano pode causar liberação tardia ou qualidade ruim. Isso pode ter um efeito dominó nas liberações subseqüentes.

IMHO o cronograma é muito apertado.

Você pode aumentar a cobertura do código escrevendo testes de unidade mais eficazes e também testes de integração específicos do ambiente.

Você pode aumentar a qualidade do código introduzindo a programação em pares e / ou revisão de código, embora isso consuma tempo ainda mais precioso.

Uma melhor estimativa dos pontos da história do usuário também pode ajudar, limitando implicitamente as histórias do usuário que entram em um único release, diminuindo o denominador na sua taxa de risco.

No geral, parece que você tem boas práticas e um bom sistema para lidar com seu ciclo extremo de lançamento. Você parece estar no caminho certo.

maple_shaft
fonte
Sim! Uma semana com um grande produto em uma linguagem compilada que precisa de testes de integração ventosos não é contínuo, é atenuante . Mantenha-o por muito tempo e você vai experimentar a mortalidade no emprego!
ZJR
+1; estamos executando iterações de três semanas no momento e descobrindo que funciona bem.
Duncan Bayne
@ZJR, você pode expandir o que quer dizer com extenuando neste contexto?
Ben
@ Duncan, nossas iterações são de duas semanas, mas estamos tentando incrementos de uma semana . Isso pode ou não ser possível / uma má ideia. O pensamento é que um incremento de uma semana conterá menos código novo e, portanto, conterá menos problemas.
Ben Ben
1
@ Ben Aston, a quantidade de código não cria problemas, prazos irrealistas, estresse e expectativas elevadas criam problemas.
maple_shaft
1

Por que não usar a implantação contínua real, onde uma confirmação (ou push) faz com que os testes sejam executados e, se os testes passam, ocorre uma implantação?

Então, se você não tiver certeza de uma alteração, faça-a em uma ramificação separada, o que ainda fará com que os testes sejam executados, mas sem implantação.

Eu acho que há mais estresse em tentar obter um tronco / mestre quebrado para a estabilidade do que em, você sabe, apenas mantê-lo estável.

Ricky Clarkson
fonte