Tableless

Busca Menu

Usando GIT para atualizar arquivos no servidor de hospedagem II – Final

Seja o primeiro a comentar por

Esta é a segunda e última parte do artigo que explica como fazer um esquema simples para deploy automático usando GIT + Bitbucket

A mesma configuração pode ser usada em qualquer servidor GIT e qualquer serviço de hospedagem que tenha acesso via ssh e git instalado

Se você ainda não leu a primeira parte, segue o link: http://tableless.com.br/usando-git-para-atualizar-arquivos-no-servidor-de-hospedagem

No artigo anterior, criamos as chaves SSH para autenticação no Bitbucket, criamos um repositório GIT e manualmente executamos o comando | git pull | para atualizar o nosso repositório.

Nessa segunda parte vamos executar o comando para atualização, de forma automatizada, sem precisar acessar o servidor. Vamos fazer um painel de controle para acompanhar os logs de deploy, mostrando se o comando foi executado com sucesso ou se aconteceu algum erro.

Gostaria de lembrar que essa é uma solução simples, existem várias maneiras de fazer deploy automatizado, eu escolhi fazer usando php e shell_exec, é mais rápido e para projetos simples isso funciona muito bem. O mesmo pode ser feito usando CGI ou Shell Script, ou ainda você pode usar um serviço online como o heroku.com, ou configurar o Capistrano, ou Jenkins, etc…

O Comando shell_exec no PHP

No manual do php:
(PHP 4, PHP 5, PHP 7)
shell_exec — Executa um comando via shell e retorna a saída inteira como uma string

Isso quer dizer que podemos executar um comando no servidor e ler o retorno desse comando, no nosso caso vamos executar o comando | git pull origin master | o mesmo comando que estávamos executando manualmente lá no servidor, lembra que tínhamos que acessar o servidor via putty, navegar até a pasta do nosso repositório e depois executar um git pull, já que isso é uma tarefa repetitiva, vamos automatizar, é isso que devemos fazer com todos os processos repetitivos.

Em muitos servidores de hospedagem esse comando é bloqueado por padrão, se estiver bloqueado você vai receber um aviso parecido com esse:

Warning:  shell_exec() has been disabled for security reasons in /var/www/deploy.php on line 10

No meu caso eu abri um chamado no painel da hospedagem, explicando que precisava da liberação para usar em um sistema de deploy automático usando GIT e prontamente fui atendido e o comando foi liberado.

Vou usar o mesmo repositório que usei para a primeira parte, https://bitbucket.org/jzonta/artigo_atualizacao_arquivos

Vamos Começar, e vamos usar um dos termos da metodologia XP – Extremme Programing, “Baby Steps”, vamos executar todo o processo em pequenos passos, eu vou atualizar o repositório no GIT com todos os passos, você pode acessar e ver todos os commits – inclusive os errados 🙂 – é bacana pra ver a evolução do código.

Vou criar uma pasta chamada deploy e dentro um arquivo chamado index.php, quando executado pelo navegador ele atualiza nosso servidor executando o comando git pull no servidor e imprimindo na tela o resultado do commnado.

A pasta deploy deve ficar dentro da pasta do seu projeto, você pode ver a estrutura que usei no repositório desse artigo no Bitbucket.

* Note que no final do comando git pull eu adicionei “2>&1” isso quer dizer que alem das saídas normais eu quero exibir as saídas de erro do nosso comando no servidor.

index.php

<!DOCTYPE html>
<html lang="pt-br">
<head>
<meta charset="utf-8"/>
<title>Usando GIT para atualizar arquivos no servidor de hospedagem</title>
</head>
<body>
	<pre>
	<?php
		$exec = shell_exec("git pull origin master 2>&1");
		echo $exec;
	?>
	</pre>
</body>
</html>

A saída na tela é a mesma que aparece quando executamos o comando lá no servidor, veja o exemplo da saída no servidor e no navegador:

comando_shell_navegador

* Lembre-se que para enviar esse arquivo ao servidor você não deve usar o ftp, faça isso utilizando o comando |git pull|, já fizemos isso na primeira parte do artigo.

Já estamos atualizando nosso servidor apenas acessando uma url em nosso navegador \o/, mas não é só isso que queremos, eu quero que essa url seja chamada sempre que eu enviar um push para o repositório, então acesse sua conta no Bitbucket e vamos configurar isso.

Acesse seu repositório, no menu lateral esquerdo, clique em “Configurações”.
Na tela configurações clique em “Webhooks” e depois em “Add Webhook”
No campo “Title” adicione um nome de sua preferência e no campo “URL” adicione o endereço para a sua url que executa o comando de atualização, no meu caso a URL é “http://joaozonta.com.br/artigo_atualizacao_arquivos/deploy/index.php”
Mas não podemos deixar essa URL aberta, porque qualquer um poderia acessar e isso iria executar o comando git pull em nosso servidor, então vamos criar um token de autenticação, junto com a URL eu passo um token que mais tarde vamos validar lá no nosso código, então a URL ficaria assim: http://joaozonta.com.br/artigo_atualizacao_arquivos/deploy/index.php?token=d41d8cd98f00b204e9800998ecf8427e

* Use este site para gerar seu token: http://www.miraclesalad.com/webtools/md5.php

adicionar_webhook

Feito isso, toda vez que enviar um push para o Bitbucket ele vai acessar a URL, e nossa url vai disparar o comando |git pull| no servidor e os arquivos serão atualizados. Nosso deploy já esta funcionando, mas eu também quero visualizar os logs, para ter maior controle sobre oque esta acontecendo.

local_git_servidor

*No seu repositório no Bitbucket, vc pode ver os requests que foram feitos entrando em “Configurações”, “Web Hooks”, ao lado do Title do seu webhook você clica em “View Requests” e pode ver todas as requisições que o Bitbucket fez para a sua URL.

Gravando Log

Primeiro vamos gerar o texto que queremos gravar no nosso arquivo de log, poderíamos apenas colocar a saída do comando shell_exec, mas vamos adicionar a data, hora e algumas quebras de linha para deixar o nosso log mais legível, veja como ficou o código:

<!DOCTYPE html>
<html lang="pt-br">
<head>
<meta charset="utf-8"/>
<title>Usando GIT para atualizar arquivos no servidor de hospedagem</title>
</head>
<body>
	<pre>
	<?php
		$exec = shell_exec("git pull origin master 2>&1");
		echo $exec;

		$textoLog = PHP_EOL."Data: ".date(d."/".m."/".Y." - ".H.":".i.":".s);
		$textoLog .= PHP_EOL.$exec;

		$arquivoLog = fopen('log.txt', 'a+');
		fwrite($arquivoLog, $textoLog);
		fclose($arquivoLog);
	?>
	</pre>
</body>
</html>

Não precisa explicar muito o código php porque é bem simples, se alguém tem dúvida dobre alguma das funções usadas é só dar uma procurada no site do php (php.net) ou no google, tem bastante material.

Se tudo está ocorrendo como planejado, quando você executar novamente seu endereço URL ele vai criar um arquivo chamado log.txt na mesma pasta, e gravar os logs neste arquivo.

Adicionando Token de Validação

Vamos deixar nosso deploy um pouco mais seguro. Lembra que na URL que adicionamos lá no webhook do Bitbucket colocamos um token? Então, agora vamos validar esse token.

Criei uma variavel chamada $token e adicionei a nossa string MD5
Depois a variavel $tokenValido recebe true se o token enviado via post ou get for igual ao token que configuramos na variavel $token, caso contrário recebe false.
Depois verificamos se $tokenValido for igual a true executa o deploy se não exibe o log e um botão para atualizar manualmente.

<?php
$token = "d41d8cd98f00b204e9800998ecf8427e";
if($_REQUEST['token'] == $token)
	$tokenValido = true;
?>
<!DOCTYPE html>
<html lang="pt-br">
<head>
<meta charset="utf-8"/>
<title>Usando GIT para atualizar arquivos no servidor de hospedagem</title>
</head>
<body>
<pre>
	<?php
		if($tokenValido) {
			$exec = shell_exec("git pull origin master 2>&1");
			echo $exec;

			$textoLog = PHP_EOL."Data: ".date(d."/".m."/".Y." - ".H.":".i.":".s);
			$textoLog .= PHP_EOL.$exec;

			$arquivoLog = fopen('log.txt', 'a+');
			fwrite($arquivoLog, $textoLog);
			fclose($arquivoLog);
		} else {
			//Deve exibir o log e um botão para para executar a atualização
		}
	?>
</pre>
</body>
</html>

Implementando a Leitura do Log e Botão Para Atualizar

No código abaixo foi adiciona a implementação que lê o arquivo de log através do comando file() e depois exibe na tela, também foi adicionado um formulário com o botão “Atualizar”, caso ocorra alguma falha na atualização automática através do webhook esse botão pode ser utilizado para forçar essa atualização e executar o nosso deploy.

<?php
$token = "d41d8cd98f00b204e9800998ecf8427e";
if($_REQUEST['token'] == $token)
	$tokenValido = true;
?>
<!DOCTYPE html>
<html lang="pt-br">
<head>
<meta charset="utf-8"/>
<title>Usando GIT para atualizar arquivos no servidor de hospedagem</title>
</head>
<body>
	<pre>
		<?php
		if($tokenValido) {
			$exec = shell_exec("git pull origin master 2>&1");
			echo $exec;

			$textoLog = PHP_EOL."Data: ".date(d."/".m."/".Y." - ".H.":".i.":".s);
			$textoLog .= PHP_EOL.$exec;

			$arquivoLog = fopen('log.txt', 'a+');
			fwrite($arquivoLog, $textoLog);
			fclose($arquivoLog);
		} else {
		?>
			<form action="index.php" method="post">
				<input type="hidden" name="token" value="d41d8cd98f00b204e9800998ecf8427e">
				<input type="submit" value="Atualizar">
			</form>
		<?php
		$texto = file('log.txt');
		foreach ($texto as $linha) {
			echo $linha;
		}
		}
		?>
	</pre>
</body>
</html>

Adicionando Autenticação

Tudo funcionando, mas qualquer um pode entrar na nossa URL, visualizar os logs e clicar no botão para atualizar o servidor.

Então vou implementar uma autenticação simples, iniciando uma sessão e usando a variável $senhaAcesso, então nossas regras seriam as seguintes:

Se receber o token, faz a validação, se estiver correto, atualiza o nosso servidor
Se receber a senhaAcesso, faz a validação se estiver correto, mostra o log e o botão para atualizar
Se não receber o token e nem a senhaAcesso mostra um form solicitando a senha

Nosso código tem apenas 3 condições no if, eu preferi deixar assim pra ficar mais fácil de entender, as condições separadas para ficar mais fácil de entender:

		if($tokenValido) {
		    // Se o toquem for válido
		    // Executa o comando git pull para atualizar o servidor e grava o log
		} else if($_SESSION['usuarioValido']) {
		    // Se o usuário estiver logado mostra o log e o botão para atualizar
		} else {
		    //Se o usuário não estiver logado mostra o formulário para logar
		}

Abaixo o código completo desta etapa:

<?php
session_start();
$token = "d41d8cd98f00b204e9800998ecf8427e";
$senhaAcesso = 'joaozonta';

if($_REQUEST['token'] == $token)
	$tokenValido = true;

if($_REQUEST['senhaAcesso'] == $senhaAcesso && empty($_SESSION['usuarioValido']))
	$_SESSION['usuarioValido'] = true;

if($_REQUEST['sair'])
	unset($_SESSION['usuarioValido']);
?>
<!DOCTYPE html>
<html lang="pt-br">
<head>
<meta charset="utf-8"/>
<title>Usando GIT para atualizar arquivos no servidor de hospedagem</title>
</head>
<body>
<pre>
	<?php
		if($tokenValido) {
			$exec = shell_exec("git pull origin master 2>&1");
			echo $exec;

			$textoLog = PHP_EOL."Data: ".date(d."/".m."/".Y." - ".H.":".i.":".s);
			$textoLog .= PHP_EOL.$exec;

			$arquivoLog = fopen('log.txt', 'a+');
			fwrite($arquivoLog, $textoLog);
			fclose($arquivoLog);
		} else if($_SESSION['usuarioValido']) {
		?>
		<form action="index.php" method="post">
			<input type="hidden" name="token" value="d41d8cd98f00b204e9800998ecf8427e">
			<input type="submit" value="Atualizar">
		</form>
		<?php
		if($_SESSION['usuarioValido'])
			echo '<p><a href="index.php?sair=true">Sair</a></p>';
			$texto = file('log.txt');
			foreach ($texto as $linha) {
				echo $linha;
			}
		} else {
		?>
		<form action="index.php" method="post">
			<div>
				<input type="text" placeholder="Senha" name="senhaAcesso"> 
			</div>
			<input type="submit" value="Acessar Sistema">
		</form>
		<?php
		}
	?>
</pre>
</body>
</html>

Conclusão

De uma maneira muito simples você pode atualizar seu servidor sem depender de um sistema complexo de deploy e sem muitas configurações.

Você pode implementar muitas outras opções para deixar o seu sistema cada vez mais completo, pode adicionar um botão para limpar o log ou adicionar o log em um banco de dados. Já imaginou mostrar um combo com os últimos commits realizados e você escolher qual desses commits você quer atualizar no servidor, podendo assim voltar e avançar versões.

Não falei sobre banco de dados nesse artigo, acho que isso pode ser tratado em outro tópico.

Você pode ver o exemplo funcionando em http://joaozonta.com.br/artigo_atualizacao_arquivos/deploy/, use a senha “joaozonta”

*No exemplo que esta no ar foram comentadas as linhas que fazem o deploy automático, está apenas simulando o funcionamento.

Fique á vontade para entrar em contato para qualquer dúvida, sugestão, crítica ou erro que encontrar nesse artigo.

João A. Zonta
joaozonta.com.br
@joaozontaweb
joao@joaozonta.com.br

Publicado no dia