As 3 leis da build

Semana passada eu implementei um negócio interessante no QMágico, daí resolvi passar aqui pra contar a história.

1. O problema:

Lá no QMágico, a gente usa o Jenkins pra fazer integração contínua. E temos um monitor visivel que fica vermelho quando a build está quebrada. Builds quebradas atrapalham o trabalho de todo mundo, e quando a build fica quebrada por bastante tempo, isso tende a ter um impacto negativo na produtividade do time.
O principal bloqueio da build quebrada é que, como não é possível dar deploy da versão, fica difícil testar suas alterações no ambiente de testes.

2. A solução:

Pra resolver isso, instituímos “As 3 leis da build”, que são as seguintes:

3leis

 

Não, mentira, são essas abaixo! hehehe

  • 1a. lei: Não comitarás em branch quebrada (Ou seja, uma branch que não tenha sido buildada com sucesso pelo Jenkins).
    Se vc quiser fazer um commit mas a branch está quebrada, vc deve providenciar que ela fique verde primeiro: Ou seja, ou vc conserta o que está quebrado, ou vai atrás da pessoa que quebrou pra ela consertar. Só depois que estiver verde, vc pode comitar suas alterações.

 

  • 2a. lei: Se vc quebrar a build, vc tem 20 minutos pra consertar. Mesmo que pra isso vc preciso desfazer seu ultimo commit.

 

  • 3a. lei: Se vc encontrar uma build quebrada há mais de 20min, e o responsável pela quebra não estiver disponível, vc tem o direto de desfazer o último commit do safado, e colocar o seu commit em cima da build verde.

Na minha interpretação, isso é o mais parecido que dá pra se ficar do conceito de “Jidoka / Stop the line” da Toyota: quando aparece um problema, tudo pára até que o problema seja resolvido.
Com uma vantagem que, no nosso caso, dá pra jogar o problema pra uma branch separada. Assim, dá pra resolver o problema com calma numa branch temporária sem atrapalhar o trabalho de todo mundo na branch principal.

Agora, pra que essas leis sejam realmente cumpridas, precisa de uma forcinha das ferramenta envolvidas no processo. Nenhum processo funciona baseado exclusivamente na boa vontade de um número grande de pessoas, por melhores que elas sejam.

Então, nosso servidor do Git agora eh capaz de rejeitar “pushes” com uma mensagem do tipo:

Seu push foi rejeitado porque essa branch estah quebrada!
desc=qm-1697[48e670a4..f88f4372] by tonylampada / DEU PAU no teste python
last_update=2015/02/23-20:30:14
Vai lah no Jenkins e ve o que tah rolando
Se vc quiser fazer um commit pra consertar a build use a palavra mahgica “WILLFIX” no comentario
(por favor nao abuse desse recurso, senao vai rolar um creu em vc)
Se o responsavel pela quebra nao estiver disponivel no momento, vc pode – e deve – voltar o commit do safado
Pra isso, basta usar o job no Jenkins “Voltar_commit”

ou então

Já tem uma build dessa branch rodando, tenta daqui a pouquinho!
desc=qm-1697[48e670a4..f88f4372] by tonylampada
last_update=2015/02/23-20:30:14

Voltar commits com o git é uma tarefa que nem todo mundo sabe fazer.
As vezes alguém pode se atrapalhar com os comandos do git e acabar “fazendo merge” se é q vc me entende.

Então pra facilitar, criamos um job no Jenkins pra isso.
Após voltar o commit de alguém, ele manda um email parecido com:

Ola tonylampada, tudo bem?
Aqui eh o seu amigo Jenkins véio de guerra.
Tenho uma notícia que talvez vc não goste, mas que eh pro bem do time, e do processo de desenvolvimento como um todo.
Entao, sabe o zorak… ele voltou seu commit. Provavelmente pq vc quebrou a build.
Ele deixou um recadinho pra vc, veja:

ow! q p*** eh essa???

Mas fica tranquilo que eu salvei seu trabalho. Veja as minhas instruções pra você no final do email.
——————————————
Historico:
* 91bae56 – pep8 (2015-02-23 16:43:12 -0300 ) <tonylampada>
* 859a608 – quebradeira geral (2015-02-23 16:42:46 -0300 ) <tonylampada>
* beb04a6 – Quebra mais quebra mais (2015-02-23 16:41:11 -0300 ) <tonylampada>
* a9f9192 – teste: quebrando a build! (2015-02-23 16:40:46 -0300 ) <tonylampada>
* a502197 – Corrigindo textos da edição de provas. (2015-02-23 16:37:04 -0300 ) <Luiz Edmundo Mizutani>
Voltou para: a5021970
Quem mandou voltar: zorak
Branch salva: tonylampada_91bae56
——————————————
O estado do seu trabalho está salvo na branch tonylampada_91bae56.
Basta que voce continue seu trabalho lá, e assim que a build nessa branch estiver verde, vc pode fazer um merge de volta pra dev, flw?
Boa sorte aih, fique longe das gambiarras e mantenha os amiguinhos longe tambem!
Um grande abraço do seu amigo
Jenkins

3. O impacto

Esse esquema já está em vigor no QMágico há quase 1 semana e o efeito é interessantíssimo.
É muito difícil a build ficar vermelha. E normalmente, quando fica, é numa branch temporaria diferente da branch principal onde todo mundo trabalha.
Eu fiquei até meio frustrado de até agora não ter podido voltar o commit de ninguém! rs
Ou seja, como ninguém quer ser vítima da 3a lei, todo mundo tá praticando a 2a. direitinho (que é a única lei que a gente não força via automação)

O gráfico abaixo mostra a quantidade de horas por dia em que a build ficava quebrada (sem nenhum filtro por branch. O ideal seria filtrar apenas pela branch de desenvolvimento, mas isso não era tão trivial de extrair do Jenkins)

build_quebrada

No dia 24/2, a gente habilitou as 3 leis. De lá pra cá o pior dia foi 4/3 que teve 2h30m de build quebrada – e ainda assim parece q isso é uma anomalia.

Repare que no dia 10/2 nós tivemos ~22h de build quebrada – que também não é normal no nosso dia a dia, só que esse tipo de coisa nunca mais deverá acontecer.

4. A receita

Implementar isso não é tão difícil. Precisa de um pouquinho de bash, python e criatividade.

  • a) O Jenkins precisa expor o status das branches.

Toda build do projeto atualiza o arquivo /var/lib/jenkins/userContent/status_qmagico.json, que é automaticamente compartilhado pelo Jenkins na URL jenkins.meudominio.com/userContent/status_qmagico.json

O conteudo desse arquivo é algo tipo [1]

E o script usado pra atualizá-lo é um programinha python como [2].

O a build do projeto então usa esse script pra setar o status da branch como “BUILDING”, “SUCCESS” e “FAIL”.

b) No servidor do git, vc precisa criar um “pre-receive hook”, ou seja, um script que é executado no servidor toda vida que alguém faz um push: O push só é aceito se o script sair com retorno 0, além disso, tudo que o script mandar pra saída padrão aparece pro programador que fez o push.

No nosso caso, nosso servidor git fica dentro de uma instância do Gitlab.
Daí é só criar um script aqui “/opt/gitlab/embedded/service/gitlab-shell/hooks/pre-receive”

O que eu fiz foi partir desse exemplo (http://www.stavros.io/posts/pep8-git-hooks/) (que é um script pra rejeitar pushes se o codigo nao obedecer alguns padrões de codificação python) eu fui mexendo pra ele fazer o que eu precisava.

Uma parte que deu trabalho foi encontrar o encantamento correto pra buscar o arquivo de status.
Veja como a função em bash que faz valer a 1a lei: [3]

Obs: Esse XXXX aih no lugar do password não é a minha senha do jenkins. É um “API TOKEN” que tem disponível na página de configuração do usuario do jenkins.

E o arquivo “$TEMPDIR/ci/primeiraleidabuild.py” [4] é que interpreta o json.

E é isso aí. Espero que seja útil!

Até a próxima.

4 comentários em “As 3 leis da build

Deixe uma resposta

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair / Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair / Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair / Alterar )

Foto do Google+

Você está comentando utilizando sua conta Google+. Sair / Alterar )

Conectando a %s