Hyde Park - githubless gh-pages with gitolite

 ________________________________________ 
< Content-type: text/plain. You feel me? >
 ---------------------------------------- 
        \   ^__^
         \  (OO)\_______
            (__)\       )\/\
                ||----w |
                ||     ||

Hyde Park is a git-triggered jekyll [etc.] static site generation bot (you push - it builds).

There are many complex ways to do this, but IMHO — this one's simple (from experience) 😉.

It is meant for internal use inside organizations where you want to collaborate on tomorrow's content without the risk of it leaking too soon. (think political campaign sites ;) ).

Front end (what the 99% non-geeks get to see) is a static site with SSL and basic auth (if you want to read, you nead a user/password). Backend is gitolite (if you want to collab, you send an ssh key).

hydepark.py is the cgi script that gets trigerred by git's post-receive hook when you push. See below how to create such a hook and tell gitolite which repos need to trigger it, but what the hook does is a GET to the cgi sctipt with something like ?repo=bob/howto&branch=refs/heads/preview

The cgi script checks config.py to see whether the branch bob/howto/refs/heads/preview has a build script it should trigger, and if it does - launches it.

You need to copy config.py.example to config.py and edit it.

env-jekyll is a tweak to setup a machine-specific environment so that jekyll can run (e.g. if you've installed your personal copy of jekyll).

If you have such a problem, copy env-jekyll.example to env-jekyll and edit it.

Another tweak is _config-hydepark.yml that gets copied to _config.yml before we build. This lets you define site.baseurl and other deploymet-specific parameters.

.htaccess files

We can't allow users to push .htaccess files because then they (or whoever steals their notebooks) can enable cgi-bin and run arbitrary code. On the other hand, we want to let users control who gets read access to their sites. What we do is make sure .htacess files are handled outside the scope of the git repo.

First, we need an .htaccess file for the root hydepark folder. You can user .htaccess.example as a basis. You also need to create the .htpasswords file using the htpasswd utility. It should at least contain the user githook (which is what the gitolite server uses in order to trigger hydepark.py), but you should probably have at least one additional user for yourself 😉.

This takes care of the root folder. Now lets see what happens at specific site folders.

The default: intranet-wide permissions

You (the admin) prepare a .htaccess.default file that gets copied by the deploy-*.sh scripts into the root folder of a site after building (and removing all existing .htaccess files). You can use .htaccess.default.example as a basis.

The Require valid-user line means that whoever has a user/password to the hydepark's web server can view the site (if they know the URL, but since some sites are forks of public ones, it's often easy to guess).

Restricting access to specific users

If Alice wants to only allow alice and bob access to alice/myproject/preview, you can copy .htaccess.alice.myproject.preview.example to .htaccess.alice.myproject.preview, and you're done (it contains the line Require user alice bob 😉). The deploy-*.sh script will find that file and use it as the site's .htaccess (instead of using .htaccess.default).

_plugins

By default, Jekyll looks for plugins in ./_plugins but this would let users run arbitrary Ruby code, so — as you can see at deploy-*.sh — we do the Jekyll builds with -p $SCRIPT_DIR/_plugins. This means you should create _plugins/ under this folder (even if you leave it empty), and you can put there plugins you trust aren't malware 😉.

Gitolite side

Create local/hooks/repo-specific/hydepark-hook with chmod 700 containing something like:

#!/bin/sh
BRANCH=`sed 's/.* //'`
echo Doing Hyde Park build for $GL_REPO/$BRANCH
curl "https://USER:PASSWORD@example.org/hydepark/hydepark.py/?repo=$GL_REPO&branch=$BRANCH"

See here how you can manage hooks as part of the gitolite-admin repo.

For each project that has one or more branches that need rendering on push, do something like this at gitolite.conf:

repo alice/howto
    # ...
    R       = hydepark
    option hook.post-receive = hydepark-hook

Note that the hydepark user is verified with a public SSH key, and the user running the hydepark.py cgi (i.e. the web server's user) should have the corresponding private key at its ~/.ssh/.

When you push, you're supposed to see the result of the hydepark.py script on the console:

No deployment for "alice/howto/refs/heads/master"

On the web server box, you need to define which branch[es] get[s] rendered and how by editing config.py:

DEPLOYMENT = {
    # ...
    'alice/howto/refs/heads/master':'deploy-jekyll.sh',
}

That's it: simple things are [relatively] simple, and complex things are [quite] possible ;)