Neste artigo, vou mostrar como fazer um deploy automático de um site em um servidor, no meu caso na DreamHost, usando a funcionalidade Webhooks do Bitbucket.
Como funciona
- Você faz commit e push para seu repositório no Bitbucket
- O Bitbucket fará um POST na URL que você configurou de acordo com algumas regras
- Esse POST acionará o script de deploy que fará pull das alterações em seu servidor
Preparando ambiente
Primeiramente você precisará da chave pública do seu servidor para poder se comunicar com o Bitbucket usando SSH sem senha. Esta chave geralmente fica no caminho:
/home/user/.ssh/id_rsa.pub
Caso a pasta .ssh não exista no diretório home do usuário, basta executar o comando ssh-keygen
.
Copie o conteúdo do arquivo id_rsa.pub e adicione no seu repositório em Settings > Deployment Keys.
Clonando repositório
Na DreamHost, os arquivos do seu site ficam no diretório /home/user/meudominio.com/
. Logo, para clonar oprojeto nesta pasta exitem duas formas: (1) clonando diretamente nesse diretório ou (2) clonando em outro lugar qualquer e fazer um link simbólico para o caminho desejado. Para isso, execute os comandos abaixo:
# Garante que está na raiz do usuário cd ~ # Remove pasta do site atual # Isso deletará todos os arquivos do seu domínio, # então tome cuidado rm -rf meudominio.com # (1) Para clonar diretamente git clone [email protected]:usuario/projeto.git meudominio.com # OU (2) Com link simbólico git clone [email protected]:usuario/projeto.git ln -s meuprojeto/caminho/para/arquivos/ meudominio.com
Script de deploy
Para fazer toda a mágica, precisamos de um script que execute os comandos desejados no git. Para isso, usei o seguinte PHP:
<?php /** * Retirado de http://brandonsummers.name/blog/2012/02/10/using-bitbucket-for-automated-deployments/ */ date_default_timezone_set('America/Sao_Paulo'); class Deploy { /** * A callback function to call after the deploy has finished. * * @var callback */ public $post_deploy; /** * The name of the file that will be used for logging deployments. Set to * FALSE to disable logging. * * @var string */ private $_log = 'deployments.log'; /** * The timestamp format used for logging. * * @link http://www.php.net/manual/en/function.date.php * @var string */ private $_date_format = 'd-m-Y H:i:sP'; /** * The name of the branch to pull from. * * @var string */ private $_branch = 'master'; /** * The name of the remote to pull from. * * @var string */ private $_remote = 'origin'; /** * The directory where your website and git repository are located, can be * a relative or absolute path * * @var string */ private $_directory; /** * Sets up defaults. * * @param string $directory Directory where your website is located * @param array $data Information about the deployment */ public function __construct($directory, $options = array()) { // Determine the directory path $this->_directory = realpath($directory).DIRECTORY_SEPARATOR; $available_options = array('log', 'date_format', 'branch', 'remote'); foreach ($options as $option => $value) { if (in_array($option, $available_options)) { $this->{'_'.$option} = $value; } } $this->log('Attempting deployment...'); } /** * Writes a message to the log file. * * @param string $message The message to write * @param string $type The type of log message (e.g. INFO, DEBUG, ERROR, etc.) */ public function log($message, $type = 'INFO') { if ($this->_log) { // Set the name of the log file $filename = $this->_log; if ( ! file_exists($filename)) { // Create the log file file_put_contents($filename, ''); // Allow anyone to write to log files chmod($filename, 0666); } // Write the message into the log file // Format: time --- type: message file_put_contents($filename, date($this->_date_format).' --- '.$type.': '.$message.PHP_EOL, FILE_APPEND); } } /** * Executes the necessary commands to deploy the website. */ public function execute() { try { // Make sure we're in the right directory exec('cd '.$this->_directory, $output); $this->log('Changing working directory... '.implode(' ', $output)); // Discard any changes to tracked files since our last deploy exec('git reset --hard HEAD', $output); $this->log('Reseting repository... '.implode(' ', $output)); // Update the local repository exec('git pull '.$this->_remote.' '.$this->_branch, $output); $this->log('Pulling in changes... '.implode(' ', $output)); // Secure the .git directory exec('chmod -R og-rx .git'); $this->log('Securing .git directory... '); if (is_callable($this->post_deploy)) { call_user_func($this->post_deploy, $this->_data); } $this->log('Deployment successful.'); } catch (Exception $e) { $this->log($e, 'ERROR'); } } } $deploy = new Deploy('/meuprojeto'); $deploy->execute();
Quando executado, ele faz pull do seu repositório, sendo possível realizar algumas configurações como de qual branch usar.
Adicione esse script em um arquivo PHP, por exemplo deploy.php, e coloque no seu projeto de forma que ele fique disponível de acessar na forma http://meudominio.com/deploy.php
.
Configurando webhook
Agora vá até as configurações do seu repositório e configure o Webhook em Settings > Webhook > Add webhook. Defina um título pra ele, na URL insira o caminho do arquivo PHP http://meudominio.com/deploy.php
e defina quando ele deve ser invocado. O padrão é ser invocado sempre que houver um push no repositório.
Terminado essa configuração, tudo deve estar funcionando. Para testar, faça push de alguma alteração e verifique se o script foi executando olhando o arquivo deployments.log
:
06-05-2016 17:12:24-03:00 --- INFO: Attempting deployment... 06-05-2016 17:12:24-03:00 --- INFO: Changing working directory... 06-05-2016 17:12:24-03:00 --- INFO: Reseting repository... HEAD is now at e1d5723 Landing page 06-05-2016 17:12:25-03:00 --- INFO: Pulling in changes... HEAD is now at e1d5723 Landing page Already up-to-date. 06-05-2016 17:12:25-03:00 --- INFO: Securing .git directory... 06-05-2016 17:12:25-03:00 --- INFO: Deployment successful.
Finalizando
Agora tudo está configurado e (deveria estar) funcionando, mas caso tenha algum problema deixe um comentário abaixo que tentarei lhe ajudar na medida do possível.
Este tutorial foi baseado no artigo Using Bitbucket for Automated Deployments.
2 respostas em “Deploy automático de um site usando Bitbucket Webhooks”
Opa, tudo beleza?
Rapaz, fiz o que você sugeriu mas não funcionou…
Na realidade não da erro nenhum, ele me da o resultado que foi executado corretamente o script… mas quando vou na pasta do projeto e dou um novamente um Git Pull ai sim ele atualiza os arquivos, no caso deveria aparecer uma mensagem que tudo estava atualizado, não é?
O que pode ser? Visto que não tem erro, o script é executado tudo…
No meu caso está acontecendo o erro abaixo.
Quando eu rodo pelo Browser apenas e quando o Bitbucket invoca o arquivo, acontece isso.
Se eu rodar o arquivo direto pelo server funciona.
Host key verification failed.
fatal: Could not read from remote repository.
Please make sure you have the correct access rights
and the repository exists.