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

Hi,

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:

    GitHub - rails/rails-master-hook

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

    \Av[\d.]+\z

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:

    https://github.com/fxn/rails-docs-server-config/blob/master/nginx.conf

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 below.

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.

Xavier

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

require 'find'

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

def gzname(file)   "#{file}.gz" end

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

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

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

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 release.

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.