Automatizando Deploy com Git

Em meus últimos projetos pessoais tenho usado o git para fazer deploy, acabei fazendo (ou não rs) essa escolha pois estava focado na entrega e não tinha muito tempo pra configurar um Capistrano Mina da vida. Esse útlimo aliás é muito bom, mas acho que talvez seja um overkill para pequenos projetos onde um git push e git pull resolveria.

Minha rotina mais comum para projetos em casa vinha sendo: fazer alteração, comitar, dar git push, acessar o servidor, dar git pull e resetar o servidor da aplicação.

Lembrando da facilidade que serviços como Heroku e OpenShift oferecem ao fazer deploy com git push, resolvi automatizar meu processo também.

Vi um post do Elton Minetto sobre o assunto, mas particularmente não gostei do git checkout -f, procurei mais um pouco e achei esse do Akita, por fim, montei a solução que atendia bem minhas necessidades, e irei apresentá-la.

Criando um Servidor Git

No servidor que deseja fazer deploy, crie a estrutura:

$ cd ~/
$ mkdir -p git_servers/meu_projeto.git
E então crie um repositório git vazio (que será o servidor):
$ cd ~/git_servers/meu_projeto.git
$ git init --bare

Criando Git Hook

Crie um arquivo post-receive dentro da pasta hooks que servirá para executar comandos após receber um git push, não esqueça de dar permissão de execução:

$ touch hooks/post-receive
$ chmod +x hooks/post-receive

Então vem a mágica:

#!/bin/sh
# /home/user/git_servers/meu_projeto.git/hooks/post-receive
echo "-- hooks --"
cd /home/user/meu_projeto
unset GIT_DIR
git pull origin master
sudo stop meu_projeto
sudo start meu_projeto

Aqui acesso a pasta do projeto no servidor (aquela que está a aplicação rodando), definimos esse unset GIT_DIR para poder executar comandos git sem precisar utilizar o prefixo env -i que o Akita usou e então damos o tradicional git pull origin master para baixar as alterações.

Os dois últimos comandos servem para reiniciar um processo via Upstart (que utilizo pra rodar o Gunicorn), só atente para o detalhe que você precisará configurar o visudo para aceitar comandos sem pedir senha.

O script acima utilizo para projetos Django, para aplicações Rails é um pouco diferente, veja:

#!/bin/bash -l
echo "-- hooks --"
cd /home/user/meu_projeto
unset GIT_DIR
git pull origin master
echo "-- installing gems --"
bundle install
echo "-- migrating database --"
rake db:migrate RAILS_ENV=production
echo "-- cleaning assets --"
rake assets:clean RAILS_ENV=production
echo "-- compiling assets --"
rake assets:precompile RAILS_ENV=production
echo "-- restarting server --"
touch tmp/restart.txt

A única diferença é que nesse script utilizamos #!/bin/bash -l para agir como um login shell e termos acesso as funções do RVM.

Fazendo Deploy

Como uso o Bitbucket para armazenar meus projetos e nem sempre após um git push local irei querer fazer deploy em produção, então adicionei uma fonte remota com git remote add deploy user@meu_dominio.com:~/git_servers/meu_projeto.git (portanto fiquei com duas: origin do Bitbucket e deploy do servidor de produção), agora toda vez que precisar fazer deploy, basta dar um git push origin master pra jogar pro Bitbucket e depois um git push deploy master. Se eu não quiser fazer deploy, rodo apenas o primeiro.

Com isso não preciso mais acessar meu servidor manualmente pra baixar as alterações e resetar o servidor de aplicação.

Abraços.

Written on November 25, 2013

Share: