Quando me tornei (de fato) gerente em meu atual emprego, fui imediatamente encarregado de um desafio: organizar a bagunça na infra. Não existia controle de acesso, todos tinham acesso a produção e homologação. Também não existia real separação de ambientes; homologação, desenvolvimento, e até produção coexistiam.
O problema do acesso é fácil. Mudei todas as senhas, começamos a utilizar o Passpack para gerenciá-las, e instalei o Gitolite para controle de acesso aos repositórios Git; uma ferramenta incrível, porém assunto para outro artigo. Mas e a separação de ambientes?
Se ninguém (ou melhor, poucos) tem acesso SSH aos servidores de desenvolvimento e homologação, como será feito o deploy? Em pouco tempo se torna óbvio que é inviável manter essa tarefa manual. Não é raro acontecerem dezenas de deploys em homologação no mesmo dia, se incumbir uma pessoa com essa responsabilidade eu anulo um desenvolvedor pleno/sênior.
Hooks são uma feature bastante subutilizada no git. A documentação que existe na web é relativamente pobre, e o man nesse caso não ajuda muito. Como githooks
é um assunto muito extenso, e para automatizar os deploys utilizo apenas um, vou abordar apenas seu funcionamento no decorrer desse post.
De forma bem simplificada, o post-update é um script executado no repositório remoto toda vez que você dá um git push
em seu repositório local. Ele é o último passo de todos os procedimentos que ocorrem após o push, o que torna impossível alterar o resultado deste envio pelo hook. Por causa desta característica, é comumente usado para notificar outros usuários ou sistemas que o push ocorreu, e se torna o candidato perfeito para fazer deploy das alterações recém-recebidas.
Para instalar um script de hook, entre no seu repositório central (aquele criado com git init --bare
) e veja que existe um diretório chamado hooks ali dentro. Copie o script de hook com seu nome apropriado para dentro deste diretório e não esqueça de adicionar permissões de execução.
Hooks locais são instalados no diretório .git/hooks dentro de seu repositório local.
Temos aqui na Pivot 2 servidores de desenvolvimento, e 2 de homologação (um de cada para Windows e Linux). Os únicos pré-requisitos é que estes servidores aceitem conexões SSH e tenham o git instalado. O fluxo de deploy se dá da seguinte forma:
dev ---push---> repositório central ---branch------master---> servidor dev
\
\---hml---> servidor hml
Ou seja, quando um desenvolvedor dá push, se ele está enviando o branch "master", o deploy é feito no servidor de desenvolvimento com o conteúdo mais atual deste branch – as modificações que acabou de enviar. Caso seja o branch "hml", o mesmo processo é feito no servidor de homologação.
Tenha em mente que o script abaixo ainda está em estado bastante imaturo e foi feito com base em nossa estrutura. Ele não é, de nenhuma forma, genérico; porém é livre para quem quiser adaptar e utilizar.
#!/bin/sh
function get_project_path()
{
echo $(pwd | sed 's/\/home\/git\/repositories\///' | sed 's/\.git$//')
}
branch=$(git rev-parse --symbolic --abbrev-ref $1)
if [ $branch == "hml" ]
then
if git remote | grep -q 'aws'
then
echo "[INFO] Deploying branch $branch to EC2"
git push aws $branch
elif git remote | grep -q 'rack'
then
echo "[INFO] Deploying branch $branch to Rackspace"
git push rack $branch
fi
elif [ $branch == "master" ]
then
# We should have a file on the repository's root dir
# indicating the OS. If we can't find it, skip deploying
# to dev server
path="~/sites/$(get_project_path | awk '{print tolower($0)}')"
if [ -e WINDOWS ]
then
ssh web@athena "cd $path && git pull origin master"
elif [ -e LINUX ]
then
ssh webserver@localhost "cd $path && git pull origin master"
fi
fi
Se você olhar com atenção vai perceber que esse script não faz absolutamente nada se duas coisas não forem feitas com antecedência:
- Deve-se criar um remote com o endereço do repositório situado no servidor de homologação;
- Para que o deploy em homologação aconteça, precisa existir um arquivo com nome WINDOWS ou LINUX na raiz do repositório central. É assim que o hook decide para onde enviar os arquivos.
Em nosso ambiente eu automatizei estas tarefas no ato de criação do repositório. Vou abordar esta etapa em outro post.
Para desabilitar temporariamente os deploys automáticos é só remover a permissão de execução do script hooks/post-update no seu repositório central.
Minha intenção com este texto era mostrar como é possível conseguir um retorno significante com um esforço relativamente baixo. Minha solução é extremamente frágil, mas já está funcionando há cerca de dois meses e nesse meio tempo economizou dezenas de horas desperdiçadas com deploys manuais.