Here at thinkWhere we’ve recently released roadNet, a tool for managing the spatial database of road layouts, roadworks and roadside assets that local authorities use to create local street gazetteers and to plan maintenance and closures. roadNet runs as a plugin on top of the excellent open source GIS package, QGIS.
During the build of roadNet, we found it useful to make each version of the code available for installation and testing via its own QGIS repository. This post explains how it works.
git, GitHub, Shippable, Docker and Amazon S3
The roadNet continuous integration (CI) system makes use of a number of cloud-based services. We use git and GitHub for version control to allow developers to track changes to the code and use separate branches to develop new features. GitHub is linked to Shippable, which watches out for new commits to the code base. This is similar to other CI systems such as Travis. When the new code is committed Shippable spins into action.
Shippable is used to check the code and to create the cloud repositories. The instructions to do this are stored in the shippable.yml file. It does this inside a docker container, which contains QGIS and all its dependencies already installed and configured.
This stage was a bit tricky to configure because QGIS, as a desktop GIS application, assumes that it is running on a desktop computer with attached display to which it can send windows and message dialogs, when infact it is running on a little bit of memory and a little bit of hard disk on a big computer in a warehouse somewhere i.e. the Amazon Cloud. The DockerFile contains the instructions to set up a fake display (or X virtual frame buffer) in the container.
Once the code has been tested a Python script pushes it out to the repository.
QGIS plugin repositories in the cloud
A QGIS plugin repository is just a web-facing folder that contains a plugins.xml file that describes the available plugins and a series of zip files containing the code. Amazon Web Services includes the S3 service, which provides ‘buckets’ for storing files. These can be configured to be accessible for the web, making them ideal for hosting repositories.
The deploy.py script contains the instructions to zip up the files, prepare plugins.xml and copy the files to S3. The core of the key function is below:
def update_repos(build_name): """ Create new repo for build, and update latest master/dev repos. :param build_name: """ deploy_to_s3(build_name) deploy_to_s3('latest_push') branch = os.getenv('BRANCH') if branch is None: return elif branch == 'develop': deploy_to_s3('latest_develop') elif branch == 'master': deploy_to_s3('latest_master')
It is so easy to create repositories that we just make lots of them. Every set of changes gets a build_name. The first ‘deploy_to_s3’ line creates a repository specifically for that build. These are all stored indefinitely. This means that just by connecting to the specific repository, we can run the code as it was at any stage during the development.
The other ‘deploy_to_s3’ lines provide convenience repositories. These get a copy of the code that was just pushed, meaning developers can connect to the latest_push and see their most recent changes. thinkWhere’s testers can connect to latest_develop and try out new features as soon as they are merged into the develop branch. Clients point their QGIS installs at the latest_master branch to ensure that they keep up with the latest stable releases.
Anyone can update to the latest version in their branch with a single click in the QGIS plugin installer.
We have found the automatic deployment of QGIS plugins to be immensely useful, facilitating both rapid development / testing feedback loops, and easy delivery of bug fixes and upgrades to the master branch. Check out roadNet today from the official QGIS plugin repository:
If you think this may be useful to you, please also have a look at the code – its all released under GPL v2.
You can install the latest stable build of roadNet in your local QGIS machine by adding our latest_master repository to your installation (Plugins > Manage and Install Plugins > Settings):