Skip to content

Instantly share code, notes, and snippets.

@gabrielgilini
Created June 26, 2012 04:14
Show Gist options
  • Save gabrielgilini/2993244 to your computer and use it in GitHub Desktop.
Save gabrielgilini/2993244 to your computer and use it in GitHub Desktop.
Deploys automatizados com git
#!/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

Deploys automatizados com git

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.

Entram os hooks

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.

post-update

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.

Os ambientes

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.

O script

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:

  1. Deve-se criar um remote com o endereço do repositório situado no servidor de homologação;
  2. 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.

Conclusão

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment