perNalin · Tech bits and humor bites

Automated Code Deployment from BitBucket to Hostgator

Long ago when I was looking for a good hosted Distributed Version Control System (DVCS), it came down to two options; GitHub or BitBucket. Of the two, I chose Bitbucket primarily because they provided free private repositories.

This post describes how to setup an automated deployment workflow from BitBucket to Hostgator.

SSH to your Hostgator terminal

Use a SSH client such as PuTTY (if you're on Windows) to connect to your Hostgator terminal. Enter the commands below to create a ssh folder and generate a public key. You'll need this key later on to enable the connection between BitBucket and HostGator.

[~]# mkdir ~/.ssh
[~]# chmod 700 ~/.ssh
[~]# cd ~/.ssh
[~]# ssh-keygen

Once you enter ssh-keygen, you'll be prompted for a pass phrase. You could either enter a phrase, or just leave it blank and hit enter. Once this command runs, it will create a set of public/private keys in the .ssh directory.

Copy the public key from id_rsa.pub. One way to do this is to output the content of this file within PuTTY, selecting that output and right-clicking to copy to the clipboard.

[~]# cat ~/.ssh/id_rsa.pub

Add the public key to BitBucket

Log in to BitBucket and go to the 'Manage Account' screen. Then select 'SSH Keys' and 'Add key'.

Enter a name for your SSH Key, and paste your public key (that key you obtained above), and save it by clicking 'Add key'.

Verify connectivity

Go back to your PuTTY session. Run the following command to verify connectivity between BitBucket and Hostgator

[~]# ssh -T git@bitbucket.org

You may be prompted with an "Are you sure you want to continue connecting" message. If so, type in "yes" to continue. If all goes well, you should see a message similar to the following.

The authenticity of host 'bitbucket.org (XXX)' can't be established.
RSA key fingerprint is XXX.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added 'bitbucket.org,XXX' (RSA) to the list of known hosts.
logged in as XXX.

You can use git or hg to connect to Bitbucket. Shell access is disabled.

Pull Code to HostGator

The good news is git is already available on Hostgator by default. How you pull your code for the first time depends on whether you're pulling it into an existing folder (such as the root folder) or pulling it in to a new subfolder. In either case you'll need to have the bitbucket SSH path to your source handy.

If you're pulling code to a subfolder, just clone your repository and you're good to go to the next step.

[~]# git clone git@bitbucket.org:<username>/<repositoryname>.git

Instead, if you're pulling your code to an existing folder such as the root folder, the above command errors out with a message that the destination path already exists and is not an empty directory. So, do the following

[~]# git init
[~]# git remote add origin git@bitbucket.org:<username/<repositoryname>.git
[~]# git fetch

After the initial clone / fetch, you should be able to pull your code manually using the following

[~]# git pull git@bitbucket.org:<username>/<repositoryname>.git

Automate the process

Create a new php file, git-hook.php, on your hosting site with the code below. Note that the exec('git pull ... ') command contains the same command that you used above to pull the code manually. Also note that the echo statements below don't really matter. You won't actually see any output unless you manually run the PHP code. So, the only code you really need is the exec statement.

<?php
echo "Begin: Pull code from BitBucket<br/>";
exec('git pull git@bitbucket.org:<username>/<repositoryname>.git', $output);
foreach ($output as $o) {
    echo $o . '<br/>';
}
echo "End: Pull code from BitBucket<br/>";

Once this file has been saved on HostGator, go back to the Settings page of your BitBucket repository and click on 'Hooks'. Then select 'POST' from the drop down and click on 'Add Hook'. In the form that appears type in the URL to the PHP file you created above and click 'Save'.

Verify the automated deployment process

Now try pushing a change to your repository. Within a few seconds your changes should now be automatically visible on the live site!

PageSpeed Insights for Jekyll Github Pages

This blog is built on Jekyll/Hyde and is hosted on Github Pages. With the upcoming scoring change on Google Search results for mobile devices I was curious about the score for my blog.

As it turns out, the initial score wasn't too bad. But I was after perfection.

  • Mobile
    • Speed: 77/100
    • User Experience: 97/100
  • Desktop
    • Overall: 90/100

These were the initial findings

Render-blocking JavaScript

This was easy enough to fix. In my case I had used the default embed code for a Typekit font. As it happens they also provide an asynchronous version. For more info refer to Typekit's support article on Embed Code.

I didn't bother with controlling FOUT (the Flash of Unstyled Text), but if you're inclined to do so, they have more tips here

Optimize CSS delivery

The fix for this was directly from Google's 'how to fix' guidelines on Optimizing CSS Delivery. I also contactonated my CSS files (hyde.css, poole .css, style.css and syntax.css) in to one minified file styles.min.css. Then loaded it asynchronously using the script below.

<script>
      var cb = function() {
        var l = document.createElement('link'); l.rel = 'stylesheet';
        l.href = 'styles.min.css';
        var h = document.getElementsByTagName('head')[0]; h.parentNode.insertBefore(l, h);
      };
      var raf = requestAnimationFrame || mozRequestAnimationFrame ||
          webkitRequestAnimationFrame || msRequestAnimationFrame;
      if (raf) raf(cb);
      else window.addEventListener('load', cb);
</script>

While this fixed the original issue (optimizing css delivery) it introduced another one. PageSpeed Insights does its analysis before the asynchronously loaded css is available. So, it reported several new 'user experience' issues . The issues it reported were clearly fixed in the live site, but I was after the perfect score. So I ended up with an ugly hack by inlining a few CSS snippets within the page template \_includes\head .html to address the new issues reported by Pagespeed Insights.

Minifying CSS

I concatanated my css files in to one file and then minified it using the YUI Compressor

Sizing Tap Targets Appropriately

This was related to the page links on the sidebar. The default template doesn't provide enough padding between the links. So adding some padding sorted it out.

.sidebar a {
    color: #fff;
    padding: 5px 0;
}

Leverage browser caching

This was the only issue I couldn't fix. My site is hosted on Github Pages, and at this point it's not possible to configure Github Pages for ctbrowser cacheing.

The Final results

  • Mobile
    • Speed: 97/100 (+20 points)
    • User Experience: 100/100 (+3 points)
  • Desktop
    • Overall: 98/100 (+8 points)

Installing Laravel on Hostgator

Have you developed a site using Laravel, and are now getting ready to deploy it? One of the first things to consider is where to host your site, and make sure that hosting provider supports the minimum server requirements for Laravel.

The instructions below are specific to installing Laravel on a Hostgator shared instance. However, this shouldn't be too different even if you're using a different hosting provider.

Sign up for a Web Hosting Service

If you don't already have a Hosting account, now is the time to get one! Here's a link to HostGator along with a discount coupon code QuickDeploy to get you started!

Connect to your hosting account terminal

Once you have a hosting account, you'll need to access its terminal. You can use any SSH client to do so. In my case I use PuTTY. You'll also need the server IP Address ready. If you don't have this already, browse over to your Hosting Service Account or CPanel to find it.

PuTTY Configuration

  • Session:
    > Host Name (or IP Address): Your domain name, or IP
    > Port: Default is 22, but if you use a shared instance try 2222
    > Connection type: SSH
  • Connection: Data
    > Auto-login username: Your HostGator username

I used default settings for everything else. If the above doesn't work and you need more help check out this link

Check PHP version

Once connected, check the PHP version of your hosted instance. You'll need to have at least PHP 5.4 to install Laravel.

username@domain [~]# php -v
PHP 5.4.38 (cli) (built: Mar 11 2015 12:43:38)

Install Composer

While you don't have to do this, i.e. you could just copy your local Laravel folder, or clone using Git, having Composer makes it much easier to install Laravel and its related packages.

requested
username@domain [~]# curl -sS https://getcomposer.org/installer | php
All settings correct for using Composer
Downloading...
Composer successfully installed to: /home1/pernalin/composer.phar
Use it: php composer.phar

Install Laravel

Install the right version of Laravel on your Host. If you don't know which Laravel version you have in Dev, use php artisan --version on your local dev console to find out.

On the PuTTY terminal enter the following command to install. Make sure you replace 'version number' with the required Laravel version. E.g. laravel/laravel=**4.2** --prefer-dist

username@domain [~]# php composer.phar create-project laravel/laravel=<version number> --prefer-dist

If you don't specify a version number, composer will install the latest distribution.

username@domain [~]# php composer.phar create-project laravel/laravel --prefer-dist

If Composer is able to find the requested version, it will begin the install.

Installing laravel/laravel (v4.2.0)
  - Installing laravel/laravel (v4.2.0)
    Downloading: 100%
Created project in /home1/username/laravel
Loading composer repositories with package information
Installing dependencies (including require-dev)
      - Installing symfony/translation (v2.5.11)
        Downloading: 100%
        ...
        ...
Application key [XXX] set successfully.

To remove a Laravel installation

If you installed the wrong version, or you need to get rid of Laravel just delete the Laravel folder and its content from your hosting site.

username@domain [~]# rm -r laravel