Monday, February 20, 2012

Keep your CI instances up to date with this handy lib

It has been awhile since I last posted on my blog and for that I apologize. I have officially become a freelance developers (which makes that donate button on the right a bit more important). It has given me time to work on some personal ventures which I will announce here in the coming months. Bottom line I can finally write the code I want to write and hopefully can continue to do so for awhile.

Given my free time I have started work on Feed Forge again (which you should check out if you haven't yet) and I decided that I wanted to provide the ability to automatically update Feed Forge without having to bother with all the git commands. The solution for this was to utilize GitHub as a remote update server and write a CodeIgniter library to perform the updates. The library basically keeps a record of the current commit that the files are on, then when the update method is called it contacts GitHub to see if there is any change between the commits. If there isn't it does nothing. If there is then it will pull down and extract a zip file of the new repo from GitHub and compare the two commits removing or replacing any files locally that were removed, added, or modified in the latest GitHub commit. The really cool thing about the library is that it doesn't require a Git instance on the local server. Meaning it should run on just about any *nix based server running PHP.

Let's get down to brass tax here.

The library only has two methods.
$this->github_updater->has_update();
This method indicates if there is an update available. It will return true if there is and false if there isn't.

$this->github_updater->update();
This method will actually perform an update if one is available. It will return true on success or false on failure.

And that is all there is to the library. However it also has a companion configuration file. The config file is vitally important to how the library works and needs to be setup properly. I will go over the different options.

github_user - [Required] This is the user name on GitHub of the account that the repo resides in.
github_repo - [Required] This is the name of the repository as it is on GitHub.
github_branch - [Required] This is the branch that you wish to perform updates from.
current_commit - [Required] This is the current commit the local files are set to. Note that you should only need to set this initially. It will be altered by the library as updates are performed.
ignored_files - This is a list of files that you do not want updated. Usually this would be config files that might be different on other servers, but you can specify anything in here.
clean_update_files - This is a flag to indicate if the library should clean up the zip file that it downloads and extracts from GitHub. This can usually be set to true.

Here is an example of the config file I was using to test with:
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');

/**
 * The user name of the git hub user who owns the repo
 */
$config['github_user'] = 'jimdoescode';

/**
 * The repo on GitHub we will be updating from
 */
$config['github_repo'] = 'Test-Auto-Updater';

/**
 * The branch to update from
 */
$config['github_branch'] = 'master';

/**
 * The current commit the files are on.
 * 
 * NOTE: You should only need to set this initially it will be
 * automatically set by the library after subsequent updates.
 */
$config['current_commit'] = 'd2605907262c932035ec16bdd2716bcd163622bb';

/**
 * A list of files to never perform an update on
 */
$config['ignored_files'] = array('application/config/config.php',
                                 'application/config/github_updater.php',
                                 'application/libraries/Github_updater.php');

/**
 * Flag to indicate if the downloaded and extracted update files
 * should be removed
 */
$config['clean_update_files'] = true;


The library is actually pretty simple and should work well in most circumstances, but I do need to stress that you should always make a backup prior to any upgrade. If used improperly this library is capable of really messing up your CodeIgniter instance so make sure you backup before you update. Also this library does not do any kind of database updates if you want those you need to do them yourself.

Here is the link to the github repo.

Well enjoy and if you like this library please consider donating and as always if you have issues let me know in the comments.

[EDIT] I just want to point out that updates can only be applied to files in the webroot. Also the library only works with relative paths so if the GitHub repo references a file in application/controllers then the library will act on the file in application/controllers of the local webroot. This means that your GitHub repo has to be a complete CodeIgniter instance.

[EDIT 2] I updated the library to allow more general ignore statements. Meaning that you can now specify entire directories to be ignored or certain file names that should be ignored. You can even specify file extensions to ignore.

[EDIT 3] Currently the library only works with public github repos. There is no authentication needed for those. If there is demand I can add support for authentication and private repos. You would also have to provide a private repo for me to test with though.