Laravel automatisch releasen met Bitbucket webhooks

In dit artikel laat ik zien hoe je GIT aanpassingen automatisch kan releasen.
Je hoeft dan niet meer naar je serveromgeving te gaan, inloggen, handmatig een GIT pull te doen, database en eventuele packages bijwerken.
In het artikel Laravel op shared webhosting zetten leg ik uit hoe je je code op je webhosting krijgt.
Dat moet eerst gebeuren voordat je verder kan met dit artikel.

Deployment scripts

We gaan 2 bestandjes aanmaken, op de volgende locatie:

  • deploy.sh
  • public/deploy.php

Deze kan je handmatig releasen omdat deze nodig zijn voor elke omgeving (staging/productie).
Dit kan via ‘File manager’ onder ‘Files’ in Cpanel of met een FTP programma zoals Filezilla.

Zet deze 2 bestandje ook in je .gitignore bestand zodat er geen problemen ontstaan.

deploy.sh
public/deploy.php

Inhoude public/deploy.php (geschikt voor PHP7)

Plaats in dit bestand de volgende inhoud:

<?php
$repo_dir = dirname(__DIR__, 1);
$web_root_dir = __DIR__;
$bash_path = 'sh';
$branchToPull = 'branch_naam';
$secret = 'XXX';
$deployLog = __DIR__ . '/../storage/logs/deploy.log';

// Full path to git binary is required if git is not in your PHP user's path. Otherwise just use 'git'.
$git_bin_path = 'git';

$update = false;

// Extra not really secure but still an extra check.
if (!isset($_GET['secret']) || $_GET['secret'] != $secret) {
    file_put_contents($deployLog, date('m/d/Y h:i:s a') . " Secret key is not correct\n", FILE_APPEND);
    die('Secret is not correct!');
}

// Parse data from Bitbucket hook payload
$payload = json_decode( file_get_contents( 'php://input' ), true );

if(empty($payload)) {
    die("Payload is empty");
}

if (empty($payload->commits)){
    // When merging and pushing to bitbucket, the commits array will be empty.
    // In this case there is no way to know what branch was pushed to, so we will do an update.
    $update = true;
    $branch = $branchToPull;
} else {
    foreach ($payload->commits as $commit) {
        $branch = $commit->branch;
        if ($branch === $branchToPull || isset($commit->branches) && in_array($branchToPull, $commit->branches)) {
            $update = true;
            break;
        }
    }
}

if ($update) {
    // Call the bash script if this script exists.
    if (file_exists($repo_dir . '/deploy.sh')) {
        exec('cd ' . $repo_dir . ' && ' . $bash_path . ' deploy.sh', $output, $result);
    }
    else {
        file_put_contents($deployLog, date('m/d/Y h:i:s a') . " Deployment bash file does not exists\n", FILE_APPEND);
    }

    // Log the deployment
    $commit_hash = shell_exec('cd ' . $repo_dir . ' && ' . $git_bin_path  . ' rev-parse --short HEAD');
    file_put_contents($deployLog, date('m/d/Y h:i:s a') . " Deployed branch: " .  $branch . " Commit: " . $commit_hash . "\n", FILE_APPEND);
}
?>

Pas de volgende configuratie aan mocht dat nodig zijn:

$repo_dir = dirname(__DIR__, 1);
$web_root_dir = __DIR__;
$bash_path = 'sh';
$branchToPull = 'branch_naam';
$secret = 'XXX';

// Full path to git binary is required if git is not in your PHP user's path. Otherwise just use 'git'.
$git_bin_path = 'git';

Wil je op deze omgeving niet product hebben maar bijvoorbeeld de staging branch pas dan $branchToPull aan naar ‘staging’.
$secret = een extra string, mag je zelf verzinnen deze heb je straks nodig bij het aanmaken van de webhook.

Wat doet het script verder

Later gaan we een webhook maken die bij een push commando dit script aanroept op je webserver.

  • Hij kijkt of secret, de string die je hierboven hebt gelijk is. Zo niet schrijft hij dat web in de deploy log.
  • Kijkt of er data van Bitbucket is
  • Daarna kijkt het script of een pull nodig is voor deze branch
  • Bij de $update zal hij het deploy.sh script aanroepen
  • In het laatste stukje code zal hij de aanvraag wegschrijven in een log bestandje (deploy.log)

Inhoud deploy.sh

#!/bin/sh

# activate maintenance mode
php artisan down

# update source code
git pull origin branch_naam

# update PHP dependencies
export COMPOSER_HOME='/tmp/composer'
composer install --no-interaction --no-dev --prefer-dist
	# --no-interaction	Do not ask any interactive question
	# --no-dev		Disables installation of require-dev packages.
	# --prefer-dist		Forces installation from package dist even for dev versions.


# clear cache
php artisan cache:clear

# clear config cache
php artisan config:clear

# cache config
php artisan config:cache

# restart queues
php artisan -v queue:restart

# update database
php artisan migrate --force
	# --force		Required to run when in production.

# stop maintenance mode
php artisan up

Wat doet deploy.sh

  • Hij zet de Laravel applicatie eerst in de onderhoud modus
  • Doet een pull Pas de naam hier ook van branch_naam aan, bijvoorbeeld master om wijzigingen door te voeren
  • Update de PHP packages
  • Cache verwijderd
  • queue herstart
  • Werkt database wijzigingen bij
  • Zet de website weer uit onderhoud modues

Webhook aanmaken op Bitbucket

De laatste stap is het aanmaken van een webhook zodat er bij een GIT push je code ook de web omgeving komt.
Ga naar je repository op bitbucket.org -> webhooks en klik op de button ‘add webhook’

Webhook toevoegen in Bitbucket

Vul hier het volgende in:

  • Title = Titel van deze webhook, bijvoorbeeld ‘Push naar productie’
  • Url, deze moet gaan naar je deploy.php script + verzin een secret, https://url_naar_jouw_website.nl/deploy.php?secret=XXX
  • Laat de overige instellingen zo staan en klik op de button ‘Save’
  • Klik op het linkje ‘view request’ en klik op de button ‘Enable history’

Instellingen nieuwe webhook aanmaken in Bitbucket

Releasen

Als je de 2 bestandjes (public/deploy.php en deploy.sh) op je webserver hebt staan zou je een automatische release kunnen doen.

Als dat is gedaan zou je bij de webhook deze moeten terug zien bij ‘view requests’.

Historie webhook in Bitbucket

Release log

Na een automatische release (of bij een foutmelding hiervan) zal dit in een log bestandje verwerkt worden, de commit die gedaan is. Deze kan je terugvinden in ‘Storage/logs/deploy.log’.

Plaats een reactie