Grav Development with GitHub - Part 2

Complete your new GitHub workflow...

10 mins

In this second part of our two-part series, we will dive into using GitHub to manage our locally-developed site and integrate it with our live production environment. If you have not already done so, please ensure you have a working local Grav site as outlined in Part1 of this series.

So enough blathering, it's time to get our feet wet with GitHub!

GitHub Overview

In case you have been under a rock for the last few years, you will already have heard of GitHub. However, there are some common misconceptions about with GitHub actually is, so let's clear those up first with eloquent Wikipedia definition:

GitHub is a Git repository web-based hosting service, which offers all of the distributed revision control and source code management (SCM) functionality of Git as well as adding its own features. Unlike Git, which is strictly a command-line tool, GitHub provides a web-based graphical interface and desktop as well as mobile integration. It also provides access control and several collaboration features such as wikis, task management, and bug tracking and feature requests for every project. Wikipedia

So really, GitHub is a pretty Web wrapper around the Git source control software that is pretty much de-facto these days for revision management of software development. GitHub also has many great tools and capabilities that simplify the process of managing code. It is particularly popular in the open source community and Grav itself along with all it's associated plugins uses GitHub.

The important part for our sake is the ability to push commits to GitHub, using GitHub directly to make edits, and then hooking GitHub up so that changes are automatically propagated to our live production environment.

GitHub Account and Client

The first step in this process is to create a GitHub account if you do not already have one.

I will assume that you're a novice GitHub user and have never used Git before. If you have a different preferred client, or workflow, feel free to substitute that in place.

GitHub has created their own client for Mac and Windows, and although visually slightly different, they are actually quite similar in functionality. Download and install the appropriate version for your platform. Launch it and login with your GitHub account credentials.

Creating a Repository

The next step in the process is to take our Grav site and add it to GitHub. We really have two options here, and each have their pros and cons:

1. Add the entire Grav site to GitHub

Adding your entire site to GitHub means that your live environment will end up looking identical to your local environment. There's less to maintain on the live site, but it also means it's not as easy to have different setups or configurations. Depending on your scenario, this is not a bad thing.

2. Add only the User folder to GitHub

Grav was designed in such a way that everything user-related is contained in the user/ folder. This folder contains your content, plugins, themes, and configuration. This is the dynamic part of your site, the bits that commonly change. However, if you only store your user folder then you will have to update Grav on the live site, independently and manually from the items in your user folder. It also means you can have more control over the setup of Grav in each environment.

For the sake of this tutorial, we will go with option 1 as it's a simpler process and means our local and production environments are exactly mirrored. If you already have completed part 1 of this series, you will have a working local Grav site in /Applications/MAMP/htdocs/grav-blog. If you didn't complete part 1, or just have another working Grav site, feel free to use that information where appropriate.

Create a .gitignore File

Before we go any further, we want to create a .gitignore file so that git will ignore certain folders that contain things such as cache files, images, logs, etc. We will recreate these on the server-side later on in the process.

Simply create a file: /Applications/MAMP/htdocs/grav-blog/.gitignore and paste in these settings:

# Grav Specific
.sass-cache
composer.lock
cache/*
assets/*
logs/*
images/*
user/data/*

# OS Generated
.DS_Store*
ehthumbs.db
Icon?
Thumbs.db
*.swp
Localhost to GitHub.com

In the GitHub client, click the + (plus) button in the top-left corner of the window. Choose the Add tab from this pop-up, and select the path to your Grav site (/Applications/MAMP/htdocs/grav-blog):

Click the Create & Add Repository button. This will then take you back to the application showing you a window with lots of files listed and a NEW tag displayed next to each. This means that all these files are new additions to the repository but are uncommitted.

Next enter an initial commit message in the Summary box, such as Initial commit, and hit the Commit button. At this point, you have not pushed anything to github.com, you merely have made a commit on your local computer. When completed you will see a list of Unsynced Commits on this page. You can continue to make incremental commits as you need, and they will show up in this unsynced list with the summary commit message to help you identify them.

To actually get these files uploaded to GitHub, you need to click the Publish button in the top-right of the window.

Click that button now and for this initial commit, you will get a panel to provide more information regarding how to setup the repository. You can probably leave the name as-is, but provide a short description as shown.

Also, depending on whether or not you have a free or paid GitHub account, you will have the option to have the code be public or private. Click Push Repository to push your site up to the GitHub server.

When complete you should be able to see your repository visible on the GitHub site:

Sweet! Your Grav blog site is now on GitHub.

Install GitHub Repo in Production

Setting up an automatic GitHub webhook requires you having SSH access to the web server, and also git installed on that server. I will use a SiteGround shared hosting account I have for this process.

Full details on how to best setup your hosting environment can be found in the Grav Documentation.

Our first task is to use git to grab the latest version of our repository and copy it down to the server. For this you will need to SSH to your web server and navigate to your www or public_html folder. You next need to decide if this site is going to be installed at the root of your site or in a sub-folder. For the sake of this tutorial, I will use the sub-folder grav-blog.

NOTE: You can get the clone URL from the right side-bar on your GitHub repository page.

$ cd ~/public_html
$ git clone https://github.com/rhukster/grav-blog.git

Alternatively, if you wanted to clone directly into the root of your public_html folder, add a space and period:

$ cd ~/public_html
$ git clone https://github.com/rhukster/grav-blog.git .

This will checkout your currently committed site on your server.

We now have to manually create the directories that we specifically ignored via the .gitignore file:

$ cd ~/public_html/grav-blog
$ mkdir cache assets logs images user/data

At this point, you should be able to point your browser directly to the production site at this point and you should see the same site you had installed locally.

The GitHub Publishing Process

So far, so good! Let's test making a local, change, committing, pushing, then manually pulling to ensure the entire process works:

  1. Open the local file: /Applications/MAMP/htdocs/grav-blog/user/pages/01.blog/sunshine-in-the-hills/item.md in your text editor and change the title to Sunshine in the Mountains. Then save.

  2. Look at your GitHub client application, and it should of detected your local changes in the Uncommitted Changes section:

  3. Add a new commit message like Changed title of Sunshine blog post, in the Summary field, and click Commit.

  4. Click the Sync button in the top right to synchronize these changes with GitHub.

  5. In the SSH terminal connected to your live site type the following:
$ cd ~/public_html/grav-blog
$ git pull

You should see some output similar to this:

remote: Counting objects: 7, done.
remote: Compressing objects: 100% (3/3), done.
remote: Total 7 (delta 4), reused 7 (delta 4)
Unpacking objects: 100% (7/7), done.
From https://github.com/rhukster/grav-blog
   88c164c..9c3dabd  master     -> origin/master
Updating 88c164c..9c3dabd
Fast-forward
 user/pages/01.blog/sunshine-in-the-hills/item.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

This shows you that the page was updated and modified. Reloading the browser should show you the same change you made on your local site.

Woohoo! You now have your production site hooked up with GitHub. Now to automate this.

Automatic Webhook

The final step in this process is to setup a GitHub Webhook to automatically update your site when you commit and push modifications via GitHub.

GitHub needs a URL it can hit to trigger the event when a push has occurred. Let's create a PHP file for it on our production environment, and let's call that file ~/public_html/___github-refresher.php.

NOTE: It's actually advisable to use your own and unique name for this webhook URL, so feel free

<?php
date_default_timezone_set('America/Los_Angeles');
ignore_user_abort(true);
set_time_limit(0);

$repo          = '~/public_html/grav-blog';
$branch        = 'master';
$output        = array();

// update github Repo
$output[] = date('Y-m-d, H:i:s', time()) . "\n";
$output[] = "GitHub Pull\n============================\n" . shell_exec('cd '.$repo.' && git pull origin '.$branch);

// redirect output to logs
file_put_contents(rtrim(getcwd(), '/').'/___github-log.txt', implode("\n", $output) . "\n----------------------------\n", FILE_APPEND);

You might need to adjust this script to reference your repo path instead of ~/public_html/grav-blog. Every time this runs, it should append to the ___github-log.txt log file.

We can give this a quick test from the terminal by typing:

$ php ___github-refresher.php
From https://github.com/rhukster/grav-blog
 * branch            master     -> FETCH_HEAD

Next, we will need to create an SSH public and private key on the production server, so back to SSH we go!

$ ssh-keygen -t rsa

Hit return several times accepting the default values until you are back at the prompt. This process creates a public key (.ssh/id_rsa.pub) and a private key (.ssh/id_rsa).

IMPORTANT: Never revealor put the private key anywhere, only ever use your public key.

On your GitHub.com on your repository page, click the Settings option in the right sidebar. Then, click Deploy keys in the left sidebar, provide a title, and then paste the contents of the id_rsa.pub public key you generated on your server.

Once this is done, click the green Add key button at the bottom of the form.

Once your deploy key has been added, we can proceed to the last configuration step, adding the Webhook. In the left sidebar of Settings, click the Webhooks & Services option. Enter the URL to your PHP webhook URL and leave all the other options at their defaults, and click the green Add webhook button.

You should check both the ___github-log.txt log file to make sure you see the test payload that GitHub sent, also you can click back in to the webhook in GitHub settings, and look in the Recent Deliveries list. Check to make sure you have a green 200 response code, this means GitHub was able to reach your webhook URL successfully.

Testing the Automated Webhook

Now we have everything setup and configured, we can test the whole process. Just repeat the first four steps in the GitHub Publishing Process outlined above, this time changing another page title.

If everything is working correctly a few seconds after you synchronize in the GitHub client, you should see your changes not only on the GitHub.com repository, but also on your live production server!

Phew! I know that was a lot of information, and hopefully you were able to understand it. Let me know in the comments if you have any further questions.