Arquivo Mensal: Agosto 2014

Usando o Git para Deployment de Websites

Há uns tempos atrás, depois de vários anos a usar SVN, e de uma breve passagem pelo Mercurial, decidi converter os meus repositórios de código para Git. Ao longo dos últimos meses tenho aprendido a usar este sistema cada vez melhor, muito com a ajuda do Google.

No meio das muitas pesquisas que efectuei, encontrei alguns artigos sobre a utilização do Git para efectuar o deployment de aplicações web. Decidi então investigar um pouco mais este assunto, e ver até que ponto podia tirar partido de um sistema do género. O resultado foi um sistema que me permite fazer o deployment de uma aplicação web através de um comando git push para um determinado repositório no servidor de produção. O Git do servidor encarrega-se de colocar as alterações enviadas online, num website de testes ou de produção, dependendo do branch em causa. A solução é bastante simples, e passa pela utilização de hooks, que são basicamente scripts executadas automaticamente em conjunto com outras acções do Git.

O primeiro passo para colocar o sistema a funcionar passa por criar um repositório Git no servidor remoto.  Neste artigo vamos chamar-lhe repo, e vamos colocá-lo em /var/git. Isto pode ser feito através dos comandos:

mkdir -p /var/git/repo
cd /var/git/repo/
git init --bare

(De referir que caso use a pasta /var/git irá precisar de permissões de administrador para executar os comandos.)

De seguida passamos à criação do hook. Neste caso concreto, vamos usar um post-receive hook, que é executado no servidor no final de uma acção push. Assim, para definir o hook criamos o ficheiro hooks/post-receive, onde colocamos uma script com as acções a executar depois de um push. Na primeira linha da script vamos colocar #!/bin/bash, para indicar quem vai executar a script. Na linha seguinte colocamos read oldrev newrev refname. O objectivo desta linha é permitir saber qual o branch que foi usado no push, de modo a permitir efectuar acções diferentes em função do branch, que ficará associado à variável $refname.

Agora passamos à parte de especificar as acções a realizar. Vamos assumir que existem dois branchs, o dev e o master, e que sempre que se fizer push do dev se pretende actualizar os ficheiros na pasta /var/www/dev/ e sempre que se fizer push do master se pretende actualizar os ficheiros na pasta /var/www/main/. Para tal, vamos usar o seguinte código:

case "$refname" in
	refs/heads/master)
		echo 'Deploying files to production website...'
		GIT_WORK_TREE=/var/www/main git checkout -f master
		echo 'Fixing file permissions...'
		# chmod ...
		echo 'Done.'
		;;
	refs/heads/dev)
		echo 'Deploying files to development website...'
		GIT_WORK_TREE=/var/www/dev git checkout -f dev
		echo 'Fixing file permissions...'
		# chmod ...
		echo 'Done.'
		;;
	*)
		echo "No deployment action (unknown refname: $refname)."
		;;
esac

O comando case trata de escolher a acção apropriada. Por exemplo, no caso do branch master, usamos o comando GIT_WORK_TREE=/var/www/main git checkout -f master para actualizar os ficheiros, indicando a pasta onde os mesmos são colocados através da variável GIT_WORK_TREE. Por vezes temos também que corrigir as permissões e/ou proprietários dos ficheiros, pelo que devem ser adicionados os comandos apropriados. Também podemos imprimir algumas mensagens de feedback, que serão mais tarde mostradas no cliente que está a fazer push.

Um pormenor a ter em conta é que o utilizador usado na operação de push terá que ter permissões para realizar as referidas operações (entre outras, precisará de permissões de escrita em /var/git/repo, /var/www/main e /var/www/dev).

Depois disto podemos então adicionar o repositório remoto do servidor de produção ao nosso repositório local através do comando git remote add <id> ssh://<utilizador>@<dominio>:/var/git/repo. E pronto, agora sempre que quisermos fazer deployment das actualizações feitas na nossa cópia local basta usar o comando git push <id> master, por exemplo.

Referências

  1. http://sebduggan.com/blog/deploy-your-website-changes-using-git/
  2. https://halfthetruth.de/2011/09/13/using-git-to-deploy-a-website/
  3. http://thekeesh.com/2012/01/lightweight-deployment-with-git/
  4. http://www.janosgyerik.com/deploying-new-releases-using-git-and-the-post-receive-hook/