Integração Contínua

Objetivo

Recentemente, numa das listas de discussão que participo (.NET Architects), surgiu a discussão sobre integração continua. Fiquei um pouco surpreso. Apesar de integração contínua ser uma prática um tanto quanto antiga (a primeira referência que conheço do assunto é do livro do Kent Beck, de 1999), muita gente ainda se assusta ao falar do tema.

Essa foi minha motivação para escrever um pouco sobre integração contínua (CI – Continuous Integration) aqui.

O que é integração contínua

Primeiro vamos tentar entender o que “não é” integração contínua. Antigamente (assim espero), os desenvolvedores costumavam trabalhar em “silos”. Cada um pegava um pedaço do sistema pra fazer, fazia no seu canto e colocava-se um tempo de “integração” nos cronogramas. Esse tempo era para fazer os ajustes necessários para o lego todo se encaixar. Por exemplo: Um fazia a tela, o outro fazia o servidor, o outro as procedures de banco.

É claro que muita coisa dava errada. Nem sempre os contratos eram definidos em detalhes, muitos aspectos eram deixados de lado e na hora de integrar tudo, era uma longa dor de cabeça.

A proposta da prática de integração contínua é que ao contrário de segurar as alterações e subi-las somente no final do projeto e integrar tudo ao mesmo tempo, as pessoas devem constantemente integrar o seu trabalho ao restante do time. Lembro-me no livro original do Beck que ele tinha a proposta inclusive das pessoas fazerem o build numa máquina separada da sua máquina de desenvolvimento, justamente para evitar o famoso “na minha máquina funciona”, que gerou um dos posts mais divertidos sobre o assunto: The Works on My Machine Certification Program

Em resumo, a idéia da prática é (tradução das principais partes do wikipedia):

  • Use um repositório de controle de versão: Não, não vale uma pasta na rede compartilhada, um pen-drive com o código fonte. É um software de controle de versão que gerencie concorrência, mantenha histórico, permita que você administre branches, etc.
  • Automatize o Build: Sim, montar o seu pacote, exatamente como deveria ser entregue para seu usuário final deveria ser um processo de “um passo”. Apertar um único botão, e do outro lado deveria sair um pacote pronto, com todas as dependências resolvidas
  • Faça o build auto-testável: É uma excelente idéia juntar seus testes unitários ou mesmo de aceitação com o seu processo de build
  • Todo commit deve disparar um build: Cada vez que qualquer coisa é alterada no repositório de controle de versão, um build deve ser disparado, obviamente, disparando todo o processo de empacotamento e testes, e claro, se você já estiver neste nível de maturidade, deploy
  • Mantenha o build rápido
  • Todos devem ver o resultado do último build

Como implementar

Felizmente, hoje existem ferramentas open source fantásticas (em sua maioria melhores do que pagas) para implementar todo esse processo.

Para controle de versão, sugiro consultar a última pesquisa sobre controle de versão e também o post sobre gestão de configuração e versões.

Para a automação e criação do servidor de integração contínua, sugiro os seguintes passos:

Instale um servidor de integração contínua

Suba uma instância do seu servidor favorito. Os mais populares são:

  • Jenkins: Open-source, mais popular na comunidade Java, mas serve para buildar qualquer tipo de código fonte
  • Team city: Da JetBrains, free até uma certa quantidade de projetos. Ferramenta fantástica, muito intuitiva
  • CruiseControl.NET: Começou com a ThoughtWorks, agora parece que a comunidade open source assumiu. Foi meu favorito durante anos, mas ainda demandava muita configuração “na mão”

Existem outros também, como o próprio Team Foundation Server, Rational Team Concert, mas em geral não são tão simples e populares como os supra-citados, que suportam uma série de ferramentas de controle de versão. Aliás, esse é um ponto importantíssimo. Verifique se o servidor suporta o controle de versão que você usa.

Se você usa cvs, svn, git, garanto que não terá muito sofrimento em configurar qualquer um deles. Se você usa, TFS, VSS, RTC e outros, o máximo que posso dizer é: boa sorte. Esses controles de versão tem uma interface de linha de comando muito pobre, o que torna bem chato fazer qualquer tipo de automação.

Crie um script de build

Se você vem de plataforma Microsoft, usar o MSBuild será “natural” para você. Veja o post MSBuild in a nutshell sobre como criar os builds.

O ant é o irmão mais velho, da comunidade Java.

Esses “toolkits” de build nada mais são do que ferramentas para automatizar a execução de atividades de linha de comando. Se você não sabe trabalhar com linha de comando, aqui está uma excelente motivação para aprender. Será inevitável trabalhar direito com linha de comando para mexer com automação de build.

Os toolkits também permitem criar “tasks” customizadas, de forma que você pode utilizar todo seu conhecimento no seu framework favorito para fazer as maluquices mais improváveis em builds.

A dicas sobre automação de builds:

  • Comece de forma muito simples e depois vá tornando mais completo. Primeiro, faça o fonte compilar. Já dá para ter ganhos absurdos só fazendo isso
  • Mesmo que seu projeto não tenha testes, deixar a “infra-estrutura” pronta para receber os testes é uma boa. Por infra estrutura digo, a casca do projeto de testes e a mecânica para invocar os testes no build. A medida que o time percebe que nunca mais um teste ficará vermelho, porque o build quebra, a integração contínua pode ser uma forte aliada para alavancar os testes unitários
  • Empacotamento: O build não é somente compilar, ele também significa reunir todas as dependências necessárias para rodar a aplicação. Isso engloba: scripts de base de dados, binários externos, instaladores, etc.
  • Métricas: O MSBuildCodeMetrics é um projeto que comecei justamente com esse intuito. A idéia é chegar num nível de automação que se alguém commitar um método com mais e X linhas ou com complexidade ciclomática superior a Y, o build quebra.
  • Manutenção de numeração de versão: Quando se ganha experiência, o processo de criar as “tags” corretamente e carimbar as versões, pode ser todo feito no servidor de integração contínua. A série automatizando o versionamento no build (Parte 1 e Parte 2) falam um pouco sobre esta idéia.

Como os builds rodam server-side, é muito importante ser disciplinado na hora de montar o servidor de build. Eu por exemplo, não instalo Visual Studio em servidor de build, justamente para que os builds quebrem ao menor sinal de que alguma dependência “estranha” foi inserida na aplicação.

Notificação do build

Mais importante do que o build quebrar ou ter sucesso, é o time saber disso! Não adianta nada o build quebrar e ninguém corrigir. Por isso, é imprescindível instalar um notificador.

Os servidores de integração contínua, geralmente mandam e-mails. Infelizmente desenvolvedores em geral não dão muita atenção para e-mails corporativos.

Eu recomendo a instalação de um notificador associado ao “system tray”. O CruiseControl.NET tem o “CCTray”, que faz isso muito bem. O Jenkins tem o hudsonTracker ou o próprio CCTray que funciona no Jenkins (particularmente uso o CCTray).

Vale a pena sair instalando de máquina em máquina o notificador.

As etapas da implantação da integração contínua

Primeiro vem a etapa da negação. Os tipos de #mimimi mais comuns que você ouvirá serão:

  • A ferramenta de controle de versão fez merge errado
  • Na minha máquina funciona
  • O servidor de build está com problema

Paciência. Vale a pena pegar caso a caso e mostrar um a um o que o desenvolvedor fez de errado. Uma vez que ele entenda, ele não vai querer passar a mesma vergonha duas vezes.

Depois da etapa da negação, vem a etapa da aceitação. Nessa etapa, as pessoas não criticam mais a estabilidade e a necessidade do processo de build, mas também não contribuem. O build fica lá quebrado, e ninguém se interessa por arrumar. É nessa hora que vale a pena discutir um pouco sobre “propriedade coletiva de código”. Se o build quebra, é problema de todos.

É importante combinar algumas regras para fazer a prática pegar. Já vi castigos físicos (não recomendado, porque eu preciso ser politicamente correto num blog), colocar dinheiro num pote (Ex.: R$1 a cada quebra de build e o dinheiro é usado depois para comprar guloseimas) e em último caso a autorização para voltar qualquer commit que quebra o build. Quebrou o build? Alguém vai lá e volta o commit e o cara tem o trabalho de se virar para colocar as coisas no lugar.

Depois da fase da aceitação, vem a fase da dependência. Desligue o servidor de build por um dia. Se ninguém reclamar, você ainda não atingiu seu objetivo. Minha experiência mostra que uma vez que o time ganhe a maturidade para trabalhar com integração continua, ele não consegue mais trabalhar sem. É a regra básica para convivência no condomínio.

Vantagens e Desvantagens

Já fiquei me perguntando várias vezes as desvantagens de trabalhar com integração contínua, e não encontrei. Realmente é uma prática, na minha opinião, básica, essencial para qualquer projeto de desenvolvimento de software.

E as vantagens? São inúmeras. Algumas delas:

  • Você pode chegar todo dia para trabalhar, atualizar o código, tendo a certeza que o fonte vai compilar e você pode começar o seu dia
  • A automação de deploy se torna viável, pois você consegue construir sua aplicação, com qualquer versão, em qualquer momento do tempo
  • Suas dependências ficam mais fáceis de monitorar. Você conhecerá todos os binários de que depende, todas as ferramentas que precisa instalar para sua aplicação funcionar, e obviamente, se alguém quebrar a regra, descobrirá rápido (porque o servidor de build não tem o componente não-autorizado instalado)
  • Seu time vai aprender a subir código fonte somente quando as coisas estiverem minimamente estáveis. Os ganhos de produtividade nisso são enormes. Ninguém fica parado esperando o outro corrigir a besteira que fez no código
  • Você ganha um “evento” para fazer qualquer automação no momento que alguém subiu alguma alteração. Com isso, consegue fazer valer uma série de regras como: métricas, consistência de scripts de banco, formatação de código, e o que mais achar necessário

Era isso.

Advertisement

4 thoughts on “Integração Contínua

  1. Muito bom, Eric. irei mostrar seu texto a todos. Foi útil inteiro.
    Sobre os castigos já vi empresa colocar um chapéu engraçado na cabeça de quem quebrou e a pessoa ficar o dia todo. :p

  2. Eric, excelente post, vc abordou o tema de forma simples o objetiva. Parabéns, muito bom!!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s