Utilizamos o Chef [3] como linguagem para produzir os scripts de implantação. Você pode considerar o Chef como uma espécie de evolução do Shell Script para automatizar tarefas em servidores remotos. Em um script Chef (chamado de "receita") você pode usar a linguagem Ruby e mais alguns construtos especiais do Chef para efetuar tarefas como executar comandos remotos, enviar arquivos, iniciar serviços, editar o crontab, criar uma base de dados, etc. Os construtos da linguagem Chef fornecem como vantagem independência de plataforma e idempotência nas ações executadas. Segue um exemplo de trecho da receita Chef que instala o Radar:
A idemporência nesse caso está no fato de que caso essa entrada já exista no Cron, o Chef não vai criar duas entradas iguais. A idempotência é muito importante quando a execução do script falha por algum motivo espúrio, de modo que podemos prosseguir simplesmente re-executando a mesma receita. A receita completa está aqui.
Ao criar um novo ambiente (de preferência uma máquina virtual), o primeiro passo é instalar o Chef e executar a receita de instalação do Jenkins, que é o servidor de integração contínua que utilizamos. Essa receita reutiliza uma receita da comunidade para instalar o Jenkins. Isso é uma coisa legal do Chef, há várias receitas prontas para se instalar serviços e plataformas conhecidas, como Jenkins, Tomcat, PostgreSQL, etc. Mas a nossa receita também faz o trabalho de configurar o Jenkins com dois jobs:
job deploy radar: Executa a receita de implantação do Radar. É nessa hora que são instaladas as dependências do Radar, como bancos de dados, servidores web, servidor de mensageria, configuração do crontab, etc.
Mas e para desenvolver essa receita? Não podemos ficar testando as receitas Chef em produção! Vai que a gente faz alguma besteira e não consegue consertar o servidor! Para isso usamos dois caminhos: