Where are the guides hosted?

I'm currently looking to make a recommendation to another open source project with regards to versioning their guides. I would like to recommend the guides/edge guides approach that Rails guides take. I have a couple quick questions to help be more specific in my proposal:

1. Where are the guides hosted?
2. How do you deploy? I didn't see anything in the code base for deployments, are you using something post-receive hook based?

This should help get me started. Thanks for your times!
Joe Fiorini


The Rails guides, API (edge and stable), and contrib app, all run in a
Linode I pay from my wallet.

Deployment is triggered via a webhook call from GitHub to this trivial
pure Rack application that also runs in that server:


As you see, that application just touches a file F.

In the server there is a cron job that runs every minute and runs a
shell script. If F is present it removes it and creates a lock file L
(there is a nanosecond race condition that I don't care about).
Indeed, first we check for L. If L is present the shell script just
exists, regardless of F.

The purpose of that trick is to ensure only one update is running at a
time, and to queue updates calls received while an update is
happening. To simplify the setup, since we do not care about how many
calls the applications has gotten while a process was running,
touching F is enough. If we touch it 7 times that's fine, and is super
cheap, all we need to know is that the new cron job running that does
not find the lock file L will run another update.

For edge docs there is a local working copy of the repo that gets a
git pull and then the builtin rake tasks called. These are all
straightforward shell scripts "do this, and then do that".

Then, stable docs generation runs. The shell script checks the output
of git tag and sees whether there is a new stable tag. A stable tag in
Rails is by definition one that matches


So, "v3.2.11" is a stable tag, and "v3.2.9.rc3" is not.

Stable tags have a dedicated directory in the home. We sort the stable
tags and check whether the maximum exists. If it does not (99% of the
time), there is nothing to do, exit. Otherwise we got a new stable
release. The script goes and checks out the tag in its own directory,
runs the builtin rake tasks, and makes a "stable" symlink that points
to that new directory so that nginx serves the new documents This is
the configuration of nginx:


As you see stable docs are picked up on the fly. But GiHub only calls
the Rack webhook for regular pushes, not tags, so in practice we
sometimes force the call as part of the release process (rake
publish_docs), otherwise the generation would need to wait for the
next push with commits. But the rake task only triggers the dummy
webhook, no need to tell "release the docs for this version", that is
all found out automatically as you see.

Since nginx is running with gzip_static after edge or stable docs are
generated I recursively gzip -9 all the files with the script I copy

So that is the setup. In the end is quite simple, a handful of simple
shell scripts and directory conventions, it is designed in a way that
minimizes maintenance, it basically runs autonomously.

I'd be glad to provide more details if you had further questions.


rails@dedekind:~$ cat bin/rgzip.rb
#!/usr/bin/env ruby

require 'find'

EXTENSIONS = %w(.js .html .css)

def gzname(file)

def compress(file)
  puts "compressing #{file}"
  system %(gzip -c -9 "#{file}" > "#{gzname(file)}")

def compress?(file)
  if EXTENSIONS.include?(File.extname(file))
    !File.exists?(gzname(file)) || File.mtime(gzname(file)) < File.mtime(file)

ARGV.each do |dir|
  Find.find(dir) do |file|
    compress(file) if compress?(file)

Thanks Xavier for the quick and detailed reply. I’ll post if I have additional questions while I’m working on this.

  • Joe

We sort the stable
tags and check whether the maximum exists. If it does not (99% of the
time), there is nothing to do, exit. Otherwise we got a new stable

What you are saying here is that you sort the list of tags you get from git and check whether a folder for the maximum already exists, correct? If the folder doesn’t exist, there is nothing to do, otherwise it checks out a new tag its own folder. Seems like the condition should be reversed; am I misunderstanding something?

Oh yes you are right, if the directory exists there is nothing to do,
otherwise we have a new stable release.