MagePsycho
7/6/2018 - 9:29 PM

Code Deployment via Webhook (Bitbucket)

Code Deployment via Webhook (Bitbucket)

Assumption

  • OS: Ubuntu 16.04
  • SCM: Bitbucket
  • Remote Git Repo: git@bitbucket.org:magepsycho/magepsycho.git
  • Deployment Branch: master
  • Web Root Dir: /var/www/magento2/magepsycho
  • Git Repo Dir: /var/www/magento2/magepsycho.git

Git Setup

In remote server

mkdir -p /var/www/magento2/magepsycho.git && cd $_
git clone --mirror git@bitbucket.org:magepsycho/magepsycho.git .

Note --mirror flag will create an exact mirror of the source repository, including mapping it’s remote branches. And like --bare repo, it doesn't have working tree.

SSH Key Setup

And in order to fetch from remote git repo, the ssh key should be authorized in Bitbucket. You can generate the keys in /var/www/.ssh directory and give the proper permission.

sudo chown -R www-data:www-data /var/www/.ssh

With this you should be able to communicate with remote server without entering any password.

Permission

As the web server is running as www-data user, the files must have www-data ownership else the Webhook executed via URL won't be able to write files on the specified directory. So lets fix this permission issue.

cd /var/www/magento2/
sudo chmod -R g+ws magepsycho magepsycho.git
sudo chown -R www-data:www-data magepsycho magepsycho.git

Initial checkout

# as enviroment variable
GIT_WORK_TREE=/var/www/magento2/magepsycho git checkout -f master

OR

# as flag
git --work-tree=/var/www/magento2/magepsycho  checkout -f master

Webhook Setup

cd /var/www/magento2/magepsycho
vi webhook.php

And paste the code

<?php

//'HTTP_X_EVENT_KEY' => 'repo:push' in case of Webhook request
if (!isset($_SERVER['HTTP_X_EVENT_KEY'])) {
    die ('Go away!');
}

$branch     = 'master';
$repoDir    = '/var/www/magento2/magepsycho.git';
$webRootDir = '/var/www/magento2/magepsycho';
$gitBinPath = '/usr/bin/git';
$update     = false;

$payload = json_decode(file_get_contents('php://input'));

# For Debugging Purpose
//file_put_contents($webRootDir . '/var/log/deploy.log', '[ ' . date('Y-m-d H:i:s') . " ] " . serialise($payload) . PHP_EOL, FILE_APPEND | LOCK_EX);
//file_put_contents($webRootDir . '/var/log/deploy.log', '[ ' . date('Y-m-d H:i:s') . " ] " . var_export($_SERVER, true) . PHP_EOL, FILE_APPEND | LOCK_EX);
if (isset($payload->push) && isset($payload->push->changes)) {
    foreach ($payload->push->changes as $change) {
        if ($change->new->type == 'branch' && $change->new->name == $branch) {
            $update = true;
            break;
        }
    }
}

if ($update) {
    // Do a git checkout to the web root
    exec('cd ' . $repoDir . ' && ' . $gitBinPath . ' fetch');
    exec('cd ' . $repoDir . ' && GIT_WORK_TREE=' . $webRootDir . ' ' . $gitBinPath . ' checkout -f');

    // Log the deployment
    $commitHash = shell_exec('cd ' . $repoDir . ' && ' . $gitBinPath . ' rev-parse --short HEAD');
    file_put_contents($webRootDir . '/var/log/deploy.log', '[ ' . date('Y-m-d H:i:s') . " ] Deployed branch: " .  $branch . " Commit: " . $commitHash . PHP_EOL, FILE_APPEND | LOCK_EX);

}

Login to BitBucket and browse the repository and create a webhook as:

Auto Deployment

Dev machine

cd /path/to/working/dir
# do your code
git add .
git commit -m 'Update xyz'
git push origin master

As soon as the commits are pushed, Bitbucket will trigger a request to the mentioned webhook URL and the script will do the needful.

Thanks