Reverter automaticamente confirmações que falham na construção


44

Um colega meu disse-me que ele está pensando em fazer o nosso servidor CI para commits reverter essa falharam a construção, de modo a HEADnos masteré sempre estável (como em passar a construir pelo menos).

Essa é uma prática recomendada ou pode ser mais problemática do que simplesmente deixar de funcionar masteraté que o desenvolvedor a conserte?

Meu pensamento é que a reversão do commit tornará mais complexa a tarefa de ler o commit e a correção (o desenvolvedor terá que reverter o reverso e, em seguida, confirmar a correção, o que também desorganizará o git log) e devemos deixar o commit e confirmar o consertar. Embora eu veja algumas vantagens em ter masterestabilidade, essa reversão de comprometimento de falha não me convence.

editar: não importa se é masterou qualquer outro ramo de desenvolvimento, mas a pergunta permanece a mesma: o sistema de IC deve reverter uma confirmação que falhou na compilação?

outra edição (longa): Ok, estamos usando gitde uma maneira estranha. Acreditamos que o conceito de ramificações vai contra o IC real, porque o comprometimento com uma ramificação o isola dos outros desenvolvedores e de suas alterações, e acrescenta tempo para você reintegrar sua ramificação e lidar com possíveis conflitos. Se todos se comprometerem com masteresses conflitos, eles serão reduzidos ao mínimo e cada confirmação será aprovada em todos os testes.

Obviamente, isso força você a empurrar apenas o estável (ou interrompe a construção) e a programar com mais cuidado para não quebrar a compatibilidade com versões anteriores ou alternar entre recursos ao introduzir novos recursos.

Existem trocas ao fazer o IC desta ou daquela maneira, mas isso está fora do escopo da questão (consulte a pergunta relacionada a isso). Se preferir, posso reformular a pergunta: uma pequena equipe de desenvolvedores trabalha em conjunto em um ramo de recursos. Se um desenvolvedor confirmar algo que interrompa a compilação para essa ramificação, o sistema de IC deve reverter a confirmação ou não?


38
Construções com falha nunca deveriam ter sido alcançadas masterpara começar. É para isso que as ramificações de desenvolvimento e recursos são usadas. Essas mudanças ocorrem em algo como um ramo de integração, onde você pode testar se todos os novos recursos de vários desenvolvedores trabalharão juntos e somente se isso for testado poderá entrar no master. Ou pelo menos esse é um possível fluxo de trabalho.
Thorsten Müller

1
@ thorstenmüller bem, imagine então que é em um ramo de desenvolvimento que todos os desenvolvedores usam. O sistema de IC deve reverter confirmações que falham na compilação?
Carlos Campderrós

7
Parece que você está usando o git de uma maneira estranha. Geralmente, as pessoas devem trabalhar em seus próprios repositórios em suas próprias ramificações, e enviar para o main apenas quando o CI, para sua criação pessoal, verificar que as alterações estão corretas.
21715 Wilbert

4
> "estes conflitos são reduzidos ao mínimo"; você obtém menos conflitos no momento da mesclagem, mas há muito mais problemas com mesclagens incorretas. A solução é mesclar continuamente do mestre para o seu ramo como parte do seu processo, não para não ramificar.
deworde

2
... Por que não fazer com que construções com falha não sejam aceitas no master para começar?
user253751

Respostas:


56

Eu seria contra fazer isso pelos seguintes motivos:

  • Sempre que você configura uma ferramenta automatizada para alterar o código em seu nome , existe o risco de que isso aconteça errado ou que surja uma situação em que você precise parar de fazer essa alteração (por exemplo, a versão mais recente do Google Mock teve um bug, por isso não está falhando no seu código) e você precisa perder tempo reconfigurando-o. Além disso, sempre há um pequeno risco de que a compilação falhe por causa de um erro no sistema de compilação, em vez de um erro no seu código. Para mim, o IC é ganhar confiança de que meu código está correto; isso apenas a transformaria em outra fonte de problemas em potencial para eu me preocupar.

  • Os tipos de bugs que quebram "a compilação" devem ser erros tolos que levam muito pouco tempo para serem corrigidos (como você indicou em um comentário, isso é verdade para você). Se bugs mais sutis e complicados estão entrando regularmente no master, a solução correta é não "consertá-lo mais rápido"; é preciso ter mais cuidado ao revisar as ramificações de recursos antes de serem mescladas.

  • Deixar o mestre desmontável por alguns minutos enquanto o bug é corrigido corretamente não faz mal a ninguém. Não é que o CEO verifique pessoalmente o mestre e publique o código diretamente para os clientes a qualquer momento aleatório (pelo menos, espero que não sem o seu envolvimento). No caso altamente improvável que você precisa para lançar algo antes que você possa corrigir o erro, então você pode facilmente tomar a decisão de reverter manualmente antes de publicar.


1
Além disso, apenas compilações bem-sucedidas devem acionar a criação de uma "queda de compilação" que pode ser implantada. Se uma construção falhar, não haverá queda de construção implementável; portanto, não haverá risco de que alguém publique código incorreto nos clientes.
Mark Freedman

1
Definitivamente, existe outra opção que é usada e melhor do que essa que eu acho e em uso pesado (usamos no twitter). não coloque builds com falha no master E erros bobos também são fáceis de corrigir. Veja minha resposta completa abaixo.
Dean Hiller

26

Vamos concordar com os termos primeiro.

Pessoalmente, uso os termos Construção Contínua e Integração Contínua para distinguir dois cenários diferentes:

  • Compilação Contínua: uma ferramenta que verifica periodicamente se o repositório mudou desde a última compilação e compila / testa se foi.
  • Integração Contínua: uma ferramenta que aceita solicitações de recebimento e as valida contra o cabeçote mais recente antes de torná-las visíveis.

O último, Integração Contínua, significa que o repositório que ele protege é sempre verde 1 : é estritamente melhor.

Sua pergunta realmente faz sentido para a Construção Contínua, então responderei assumindo que esta é sua configuração.

1 : As causas ambientais também podem estragar uma construção, por exemplo, um teste com um ano codificado (2015) pode começar a falhar em janeiro de 2016, um disco pode ficar cheio, ... E, claro, há a praga da instabilidade testes. Eu ignoro altivamente essas questões aqui; caso contrário, nunca chegaremos a lugar algum.


Se você tiver uma configuração de Compilação Contínua, poderá realmente automatizar a reversão de confirmações que podem ter quebrado a compilação, no entanto, existem várias sutilezas.

  • Na verdade, você não pode retirar os commits: outros colegas de trabalho já devem ter feito check-los e empurrá-los de volta na próxima vez que tentarem confirmar. Em vez disso, uma reversão deve estar comprometendo uma diferença inversa . Ah, e os colegas de trabalho odiarão você por reverter o trabalho deles quando estiver correto, pois terão que encontrar uma maneira de empurrá-lo de volta ...
  • Na verdade, você não pode apenas retirar o último commit (é uma mesclagem), mas precisa remover todos os commits ... até um certo ponto. Por exemplo, o último commit válido conhecido (cuidado ao ajustar a inicialização do sistema).
  • Você precisa pensar em causas externas (questões ambientais) e evitar uma configuração que reverta tudo para o dia 0. Felizmente, reverter para o último commit válido conhecido evita esse problema.
  • Você precisa pensar que a última compilação válida conhecida pode não ser mais compilada (problemas do ambiente); nesse caso, é provável que todas as confirmações adicionais sejam revertidas. Idealmente, em caso de falha, e antes de reverter, você faria o checkout da última compilação válida e a testaria novamente. Se passar, reverta, caso contrário, gere um alerta.

Observe que, com esse sistema, no caso de um teste instável ou de um colega de trabalho que costuma cometer uma porcaria, muitas confirmações boas são revertidas. Seus colegas de trabalho vão te odiar.


Esperançosamente, meu conto de terror expôs os problemas de permitir um repositório quebrado e agora você implementará um pipeline de Integração Contínua adequado, no qual o PR nunca é enviado diretamente para o repositório, mas, em vez disso, é colocado na fila para se fundir em uma fila de trabalho e integrado um de cada vez ( ou por roll-ups):

  • buscar o chefe do repositório localmente
  • aplicar solicitação (s) de recepção
  • construir e testar
  • em caso de sucesso, pressione para o repositório; caso contrário, marque como falha
  • passar para os próximos pedidos

Tendo tentado ambos, isso é estritamente melhor.


2
Esta é realmente a resposta certa - a solução certa é impedir que mudanças ruins cheguem ao ramo principal, não deixá-los pousar e depois ter que lidar com revertê-las.
precisa saber é o seguinte

Acho que o problema aqui é que o questionador acredita que os custos declarados de "isolar você dos outros desenvolvedores e de suas alterações" superam os benefícios. Os custos declarados são o aumento do risco de fusões não triviais, quanto mais duas pessoas divergem. Na OMI, o benefício de se isolar de um código quebrado é óbvio. O interlocutor deseja adotar uma estratégia "otimista", na qual o código quebrado está brevemente disponível masterpara ser extraído e, em seguida, corrige essa situação quando os testes falham. Todos os outros adotam uma estratégia "pessimista", como você aconselha, e apenas disponibiliza código de passagem para receber.
22815 Steve Jessop

(onde "disponível para puxar", quero dizer "puxar de master", o ideal é algo que os desenvolvedores podem fazer à toa, mas para conseguir isso, você deve adiar a confirmação masterantes de serem testados e aprovados. Se um desenvolvedor quiser cherry-pick código não testado ou testada e falhou tudo bem também, eo código está "disponível", nesse sentido, não é apenas o que eu estou me referindo a)
Steve Jessop

A solução certa é impedir que mudanças ruins cheguem a QUALQUER ramificação. Commits com falha nunca devem ser tornados públicos, nunca.
Route de milhas 26/08/15

5

Essa é uma prática recomendada ou pode ser mais problemática do que deixar o mestre quebrado até que o desenvolvedor a conserte?

Isso é problemático. Uma pessoa que decide "o HEAD principal está quebrado; vou reverter a principal alteração" é completamente diferente do que o sistema de IC que faz o mesmo.

Aqui estão algumas desvantagens:

  • Erros no processo de reversão automatizado estragarão o repositório;

  • isso pressupõe que um único changeset (o mais alto) estragou a compilação (o que não é realista)

  • Os mantenedores terão mais trabalho a fazer para corrigir o problema, do que apenas investigar e confirmar (eles também terão que examinar o histórico reverso)

Acreditamos que o conceito de ramificações vai contra o IC real, porque o comprometimento com uma ramificação o isola dos outros desenvolvedores e de suas alterações, e acrescenta tempo para você reintegrar sua ramificação e lidar com possíveis conflitos.

Essa crença (ramos vs. IC) está incorreta. Considere manter uma ramificação estável, na qual você confirma somente conjuntos de alterações testados por unidade . O restante (ramificações de recursos e ramificações locais) deve ser de responsabilidade de cada desenvolvedor e não fazer parte da sua política de IC de forma alguma.

Nos ramos de recursos, você deseja se isolar de outros desenvolvedores. Isso permite que você:

  • executar codificação exploratória

  • experimente com a base de código

  • realizar confirmações parciais (efetivamente confirmar o código não ativo) para configurar pontos de backup (no caso de você estragar), criar um histórico de alterações mais significativo (por meio de mensagens de confirmação) e fazer backup do seu trabalho e mudar completamente para outra coisa (em o tempo que você leva para escrever "git commit && git checkout")

  • execute tarefas de baixa prioridade que demoram muito tempo (por exemplo, você deseja executar uma refatoração que altera todas as 80 classes da camada de dados: você altera duas por dia, até alterar todas elas e compiladas pelo código (mas você pode fazer isso sem afetar ninguém até que você possa fazer um único commit).

Se um desenvolvedor confirmar algo que interrompa a compilação para essa ramificação, o sistema de IC deve reverter a confirmação ou não?

Não deveria. A confirmação de código estável em sua filial de IC é de responsabilidade do responsável pela entrega, não de um sistema automatizado.


2

Eu sugeriria o uso de um ambiente Gerrit + Jenkins para manter seu ramo mestre sempre em bom estado. As pessoas enviam seu novo código para a Gerrit, que aciona um trabalho de Jenkins para obter esse patch, compilações, testes e assim por diante. Se outros desenvolvedores, como o seu patch e Jenkins, concluírem seu trabalho com êxito, a Gerrit mesclará esse trecho de código ao seu ramo principal.

É um ambiente semelhante descrito por @ brian-vandenberg

Além de manter sua ramificação em boa forma, você também adiciona uma etapa de revisão de código que melhora a qualidade do código e o compartilhamento de conhecimento sobre o seu software.

[1] Jenkins https://jenkins-ci.org/

[2] Gerrit https://www.gerritcodereview.com/


1

O IC nunca deve alterar o histórico de consolidação do repositório.

A solução correta aqui é que nenhum commit seja adicionado ao branch master se eles não tiverem sido testados e verificados.

Você trabalha em ramificações de recursos, faz com que o IC seja executado automaticamente nelas e, se as construções falharem, não as junte ao mestre.

Você pode ter uma construção adicional que testa mesclagens se isso for uma preocupação, executando na ramificação de recursos e durante a construção mesclando mestre / integração / o que for na ramificação local e executando testes.


1
Isso não responde à pergunta de forma alguma. Se a construção falhar em uma ramificação de recurso, o IC deve reverter a confirmação?
Carlos Campderrós

E se a compilação for bem-sucedida na ramificação do recurso, mas falhar após a mesclagem?
Matthieu M.

@MatthieuM. mesclagem é uma consolidação, a etapa do IC que mescla reverte a compilação?
Carlos Campderrós

@ CarlosCampderrós: ​​Eu pessoalmente nunca teria uma configuração que tente reverter confirmações; muito complicado.
Matthieu M.

Eu me dirigi aos comentários.
Daenyth 21/08/2015

1

Usamos o Jenkins para nosso servidor de compilação e usamos o modelo de gatekeeper para enviar confirmações - onde uma combinação de Jenkins e gatilhos de confirmação (que garantem que os revisores de pares tenham feito seu trabalho) é o gatekeeper.

As confirmações são enviadas indiretamente por meio de um curl para o Jenkins, onde ele clona o repositório principal e extrai as confirmações a serem mescladas e executa todas as compilações necessárias (para Linux / solaris). Se todas as compilações estiverem concluídas, a confirmação será enviada por push.

Isso evita muitos, se não todos, os problemas discutidos até agora:

  • alteração da história
  • obtendo o histórico correto, se você é o desenvolvedor que precisa consertar a quebra
  • instabilidade (na forma de construções quebradas) nunca é introduzida

Também nos permite impor diretamente outros requisitos, como testes de unidade concluídos com êxito.


re: the voto negativo, você se importaria de comentar o que você não gostou sobre a minha resposta?
Brian Vandenberg

0

Quantas vezes você recebeu esse e-mail automático dizendo que seu último commit quebrou a compilação? Quantas vezes está errado? Mas agora você tem que verificar se realmente era você ou alguém que fez outro cometer ao mesmo tempo. Ou talvez fosse algo ambiental.

Se o sistema não tem certeza, certamente não quero automatizá-lo.


0

A pergunta feita é falha. Eu respeito esta afirmação embora

"Acreditamos que o conceito de ramificações vai contra o IC real, porque o comprometimento com uma ramificação o isola dos outros desenvolvedores e de suas alterações"

O que você deve fazer é seguir estas etapas

  • trabalhe fora do mestre, se quiser (isso é bom e continue puxando alterações de todos), MAS NÃO se comprometa a dominar localmente
  • Antes de confirmar suas alterações no mestre, crie uma ramificação com submit_XXXXXX
  • faça com que sua compilação automatizada pegue todas as submissões de branches_XXX
  • Opção 1: criar quebras ou mesclar quebras ... alteração rejeitada e nunca cai no mestre
  • Opção 2: construir obras, jenkins empurra o mestre e atualiza

ENTÃO, o que fazemos é colocar um gancho de confirmação do git para impedir que TODOS se comprometam a dominar. Funciona muito bem ... NENHUM constrói quebrado sempre e NENHUM reverter confirma do mestre também.

mais tarde, Dean

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.