Skip to content

Latest commit

 

History

History
755 lines (507 loc) · 33 KB

README.md

File metadata and controls

755 lines (507 loc) · 33 KB

Code Climate Build Status

Bookbinder

Note: The Bookbinder gem is now named bookbindery, and this GitHub repository is no longer a supported gem source for the gem. To use the Bookbinder gem, include the following in your book's Gemfile:

source 'https://rubygems.org'
gem 'bookbindery'

Bookbinder is a gem that binds together a unified documentation web application from disparate source material. Source material can be in markdown, HTML, or DITA, and must be stored in local directories or in git repositories. Bookbinder runs middleman to produce a Rack app that you can deploy to Cloud Foundry.

See the Bookbinder wiki for detailed information and instructions, such as how to configure credentials for multiple git services.

Installation

Note: Bookbinder requires Ruby version 2.0.0-p195 or higher.

Follow the instructions below to install Bookbinder:

  1. Add gem "bookbindery" to your Gemfile.

  2. Run bundle install to install the dependencies specified in your Gemfile.

  3. (Optional) Install the DITA Open Toolkit (DITA-OT).

    Bookbinder uses the DITA Open Toolkit (DITA-OT) to process documents written in DITA. If you have DITA sections in your book, you must install DITA-OT to process them.

    Once installed, specify the location of the DITA-OT library as an environment variable named PATH_TO_DITA_OT_LIBRARY.

    We recommend that you use the full_easy_install type for the DITA-OT library.

    Note: Ensure that the version of the DITA-OT library that you install supports the DITA version in which your documents are written.

Usage

Bookbinder is meant to be used from within a project called a book. The book includes a configuration file that describes which documentation repositories to use as source materials.

The bookbindery gem provides a set of scripts to aggregate those repositories and publish them to various locations.

Bookbinder also provides scripts for running on a Continuous Integration system that can detect when a documentation repository has been updated with new content, and that can verify a composed book is free of any dead links.

Creating a Book

  1. To create a new book on your local machine, run bookbinder generate BOOKNAME, replacing BOOKNAME with the name of your book. For example:

    $ bundle exec bookbinder generate cloud-documentation
    

    The bookbinder generate BOOKNAME command creates a directory named BOOKNAME. This directory contains the following:

    • A Gemfile referencing the bookbindery gem
    • A minimal config.yml file
    • A bin directory containing code
    • A master_middleman/source directory containing an index page
    • An empty master_middleman/build/ directory
  2. After running bookbinder generate, run bookbinder bind local to assemble your book from the repos specified in the config.yml file.

    Note: At this point, unless you've added anything to the config.yml, the config.yml contains no references to any repos, and so bookbinder will bind a book with no content.

  3. Run the following commands to start up the web site locally:

    • cd final_app
    • rackup
  4. Launch a web browser to http://localhost:9292/ to view your book.

As typically used, the disparate source materials of a book are organized into separate git repositories.

When writing documentation on your local machine, however, we recommend that you add uncommitted changes to the preview web site that you serve on your machine.

The bind local command performs this operation by gathering local sections from sibling directories of your book. These sections' directories must have the same name as their remote git repositories, but don't need to be git repositories for all commands.

Adding Basic Auth to Your Served Book

You can optionally require a username and password to access any book served by running rackup in final_app by setting the following environment variables:

  • $ export SITE_AUTH_USERNAME=<your-book-username>
  • $ export SITE_AUTH_PASSWORD=<your-book-password>

If these environment variables are not set, basic auth is not enabled.

Deploying Your Book

  • Create an AWS bucket for green builds and put info into credentials.yml
  • Set up CF spaces for staging and production and put details into credentials.yml
  • Deploy to production
  • (Optional) Register your sitemap with Google Webmaster Tools

A More Exhaustive config.yml Example

book_repo: org-name/repo-name
cred_repo: org-name/private-repo
layout_repo: org-name/master-middleman-repo

sections:
  - repository:
      name: org-name/bird-repo
      ref: 165c28e967d58e6ff23a882689c953954a7b588d
    directory: birds
    subnav_template: cool-sidebar-partial		# optional
  - repository:
      name: org-name/reptile-repo
      ref: d07101dec08a698932ef0aa2fc36316d6f7c4851
    directory: reptiles
    subnav_name: my_subnav						# optional

subnavs:										# optional
  - name: my_subnav
    topics:
    - title: My Nav Section
      base_path: birds/robins
      toc_path:  egg/index
      toc_nav_name: My Nav Overview
    - title: Other Nav Section
      base_path: reptiles
      toc_path:  index

subnav_exclusions:								# optional
  - .ignore-class
  - h2:contains("Table of Contents")

archive_menu:									# optional
  - v1.3.0.0
  - v1.2.0.0: archive-repo/your_pdf.yml

public_host: animals.example.com

template_variables:								# optional
  var_name: special-value
  other_var: 12

Assuming your book is in git, your .gitignore should contain the following entries, which are directories generated by Bookbinder:

output
final_app

master_middleman is a directory which forms the basis of your site. Middleman configuration and top-level assets, javascripts, and stylesheets should all be placed in here. You can also have ERB layout files. Each time a bind operation is run, this directory is copied to output/master_middleman. Then each section repo is copied (as a directory) into output/master_middleman/source/, before middleman is run to generate the final app.

.ruby-version is used by Ruby version managers to select the appropriate Ruby version for a given project.

Using Multiple Configuration Files

Bookbinder now supports breaking the above config.yml across multiple files.

A non-empty config.yml is still required in the book's root directory, however you may optionally include any number of valid yaml files with config in a directory named config, which you will need to create. At runtime, configuration will be loaded from config.yml and any files matching *.yml in the config directory.

Credentials Repository

The credentials repository should be a private repository, referenced in your config.yml as cred_repo. It contains credentials.yml, which must include your deployment credentials:

aws:
  access_key: AKIAIOSFODNN7EXAMPLE
  secret_key: wJalrXUtnFEMI/K7MDENG/bPxRfiCYzEXAMPLEKEY
  green_builds_bucket: s3_bucket_name
cloud_foundry:
  username: sam
  password: pel
  api_endpoint: https://api.run.pivotal.io
  organization: documentation-team
  app_name: docs
  staging_space: docs-staging
  production_space: docs-production
  staging_host:
    cfapps.io:
      - staging-route-subdomain
      - another-staging-route-subdomain
  production_host:
    cfapps.io:
      - production-route-subdomain

Layout Repository

If you specify a layout_repo: in config.yml with the full name of a git repository (e.g., cloudfoundry/my-doc-layout, which will default to GitHub), it will be downloaded for use as your book's master_middleman directory.

Any files included in your book's master_middleman/source directory will override files of the same name in the specified layout repository.

Specifying Repository Refs

By default, the bookbinder bind remote command binds the most current versions (i.e., the master branch) of the documents in the git repositories specified by the sections: of your config.yml.

Section Repository Ref

Bookbinder supports a ref key to enable use of an alternate version of a repo. The value of this key can be the name of a branch (e.g., develop), a SHA, or a tag (v19).

sections:
  - repository:
      name: org-name/bird-repo
      ref: my-branch

Example SHA:

sections:
  - repository:
      name: org-name/bird-repo
      ref: 165c28e967d58e6ff23a882689c953954a7b588d

Layout Repository Ref

Bookbinder supports a layout_repo_ref key to enable use of an alternate version of a layout repo. The value of this key can be the name of a branch (e.g., develop), a SHA, or a tag (v19).

layout_repo: cloudfoundry/my-doc-layout
layout_repo_ref: v19

Note: Bookbinder only uses the ref key when binding 'remote'. The bookbinder bind local command ignores the ref key.

Specifying a Path in Repo for Section

You can optionally specify a directory inside a source repository to use as a section with the at_path key, as follows:

sections:
  - repository:
      name: org-name/bird-repo
      at_path: scrub/jay
    directory: birds
    subnav_template: cool-sidebar-partial

In the above example, the contents of the bird-repo/scrub/jay directory would be made available at birds on your bound book.

Supported Formats

Markdown

All markdown sections must be specified within the section key of the config.yml.

DITA

Specify the following in the config.yml:

  • All DITA sections within the dita_sections key of the config.yml
  • In either the first or in each (for multiple ditamaps) DITA section listed in the config.yml, a key-value pair "ditamap_location: my-ditamap.ditamap"
  • (optional) In either the first or in each (for multiple ditamaps) DITA section listed in the config.yml, a key-value pair "ditaval_location: my-ditaval.ditaval"

For example:

dita_sections:

  - repository:
      name: org-name/bird-repo
      ref: 165c28e967d58e6ff23a882689c953954a7b588d                #optional
    directory: birds
    ditamap_location: path/to/my-special-ditamap-location.ditamap
    ditaval_location: path/to/my-special-ditaval-location.ditaval  #optional

 - repository:
 	 name: org-name/dependent-section
 	 ref: 165c28e967d58e6ff23a882689c123998a7b577e                 #optional
    directory: dependent-section
	ditamap_location: path/to/other-ditamap.ditamap
	ditaval_location: path/to/other-ditamap.ditaval                 #optional

Note: You'll need to have properly installed and specified the DITA-OT library.

DITA Dependent Sections

If a dita_section requires support DITA files from another repository, you can specify the support repository beneath a dependent_sections key in the parent repository.

Dependent sections are cloned into the parent section's directory. In the following example, the content from the dependent section will be available at <your-domain>/birds/dinosaurs/.

dita_sections:
  - repository:
      name: org-name/bird-repo
      ref: 165c28e967d58e6ff23a882689c953954a7b588d
    directory: birds
    ditamap_location: path/to/my-special-ditamap-location.ditamap
    ditaval_location: path/to/my-special-ditaval-location.ditaval
    dependent_sections:
    - repository:
        name: org-name/dinosaur-repo
        ref: pterodactyl
      directory: dinosaurs

ERB Support

Bookbinder supports ERB tags if they are specified as unicode: <%= is &lt;%= and %> is %&gt;. This enables use of helper functions.

If you want to render ERB tags as text and not evaluated as code by the Ruby interpreter, you must escape the opening ERB tag with a backslash as follows: &lt;%= is escaped as &lt;\%=. This functionality is useful for code examples, for instance.

Source Repository Link

Render a link with the URL of the current page's source repository and the text 'View the source for this page in GitHub'.

In config.yml, add:

repo_link_enabled: true

Note: This feature renders a link to a file with either the extension .html.md.erb for Markdown source files, or the extension .xml for DITA source files. Ensure that all of your files have appropriate extensions.

For this helper to render the link, you must pass the helper a whitelist of the environments where you want the link to display.

For example, suppose you have an application with staging and production environments available at 'example-staging.cfapps.io' and 'example-production.cfapps.io', and you only want this link to display in the staging environment. Whitelist staging as an included environment as illustrated in the section below.

Including source repository link

In the master_middleman dir or the layout repo's source/layouts/layout.erb, or an individual page to which you'd like to add a link. For example, add the line <%= render_repo_link(include_environments: ['staging']) %> in the desired location for your link to include the link only on sites with 'staging' in their URLs.

If you include the line below in your source/layouts/layout.erb, the feedback partial will be rendered on every page of your book that has not been specifically excluded:

<%= render_repo_link(include_environments: [<your-environments]) %>

To specifically exclude the repo link from being rendered on a page, add the line <% exclude_repo_link %> to the desired page.

Feedback Form

Render a feedback form on your book's pages.

Creating a feedback endpoint

In config.yml, add:

feedback_enabled: true

When feedback is enabled in this way, a POST endpoint is created at /api/feedback on your server, which will send a formatted email via the SendGrid Mail API. Accepted parameters for the post include: date, page_url, comments, and is_helpful.

Required credentials will need to be set in your environment for the feature to send mail. These include: SENDGRID_USERNAME, SENDGRID_API_KEY, FEEDBACK_TO, FEEDBACK_FROM.

Including feedback partial

  1. In the master_middleman dir or the layout repo's source/layouts/layout.erb, or an individual page to which you'd like to add feedback, add the line <%= yield_for_feedback %> in the desired location for your feedback form.

    If you include <%= yield_for_feedback %> in your source/layouts/layout.erb, the feedback partial will be rendered on every page of your book.

  2. Create a partial named _feedback.erb that is your feedback form, and any JavaScript required to send a valid POST to the endpoint configured above.

Excluding feedback partial on specified pages

You can choose to not have the feedback form render on specified pages if you add the following line <%= exclude_feedback %> above <%= yield_for_feedback %>.

This functionality is most useful if you have included <%= yield_for_feedback %> in your source/layouts/layout.erb and want to exclude the partial from certain pages.

Middleman Templating Helpers

Bookbinder comes with a Middleman configuration that provides a handful of helpful functions, and should work for most book projects. To use a custom Middleman configuration instead, place a config.rb file in the master_middleman directory of the book project. This will overwrite Bookbinder's config.rb.

Bookbinder provides several helper functions that can be called from within an .erb file in a doc repo, such as a layout file.

Quick Links

<%= quick_links %> produces a table of contents based on in-page anchors.

Modified Date

<%= modified_date %> displays the most recent commit date for the file in the format 'Page last updated: September 1, 2015'. You can provide an optional date format, i.e. <%= modified_date '%m/%d/%y'%>.

The modified_date helper uses the date of the most recent commit that does not contain the text "[exclude]" in its commit message.

Diagram (using Mermaid)

The mermaid_diagram helper accepts a block including text formatted to generate Mermaid diagrams. In order to use this helper, include the Mermaid package in your book.

<% mermaid_diagram do%>
 graph TB
         subgraph one
         a1-->a2
         end
         subgraph two
         b1-->b2
         end
         subgraph three
         c1-->c2
         end
         c1-->a2
<% end %>

Breadcrumbs

<%= breadcrumbs %> generates a series of breadcrumbs as a UL HTML tag. The breadcrumbs go up to the site's top-level, based on the title of each page. The bottom-most entry in the list of breadcrumbs represents the current page; the rest of the breadcrumbs show the hierarchy of directories that the page lives in. Each breadcrumb above the current page is generated by looking at the frontmatter title of the index template of that directory. If you'd like to use breadcrumb text that is different than the title, an optional 'breadcrumb' attribute can be used in the frontmatter section to override the title.

Subnavs

<%= yield_for_subnav %> inserts the appropriate subnav based on each constituent repositories' subnav_template: or subnav_name: parameter in config.yml. For a given section, only one key should be used. If both keys are specified, bookbinder will default to using the subnav_template.

The default template (\_default.erb) uses the label default and is applied to all sections unless another template is specified with subnav_template or subnav_name. Template labels are the name of the template file with extensions removed. ("sample" for a template named "sample.erb")

Subnavs for DITA

If your book includes a dita_section, Bookbinder will automatically look for a file subnav_template.erb from master_middleman/source/subnavs. No additional keys are necessary in your config.yml.

Bookbinder makes subnav links available in a JSON format at /subnavs/dita_subnav_<your-dita-section-directory>-props.json. They could be consumed with a JavaScript library (e.g. React.js) to create your subnav. Bookbinder will have written the name of the file containing the links from subnav_template.erb at a data attribute called data-props-location on 'div.nav-content'.

An example of the JSON links:

{
  "links":
  [
    {"url": "/dita-section-one/some-guide.html", "text": "my topic 1"},
    {"url": "/dita-section-one/../dita-section-dependency/some-guide-1.html", "text": "my topic dependency"}
  ]
}

Note: Use of _dita_subnav_template.erb is deprecated as of Bookbindery 7.2.0. If your DITA subnavs currently rely on this file, simply rename it to subnav_template.erb in the same location.

Subnav from Template (subnav_template):

If specified for a section, Bookbinder will look for a file of name .erb in master_middleman/source/subnavs and insert this partial into the template at the code helper.

sections:
  - repository:
      name: org-name/bird-repo
    directory: birds
    subnav_template: subnav-about-birds

Subnav from Config (subnav_name):

The subnav_name key allows users to generate their own navigation-related json by specifying topics in a config.yml and parsing the topic's specified table of contents page for navigation items, rather than defining as static HTML (as with subnav_template). This json can then be consumed with a javascript library (e.g. React.js) to create your subnav.

This feature not currently supported for DITA, though the subnav_template key does something very similar when used in dita_sections (see above).

Requirements:

  • In config.yml: a subnav_name key for each section to display the generated subnav, and a subnavs section that defines each subnav_name (as key name) used for those sections.
  • In master_middleman/source/subnavs, a file subnav_template.erb that contains html to which the generated subnav json will be appended. The file must contain one div with class 'nav-content'.
  • Properly formatted table of contents file for each topic, as specified by key toc_path
sections:
  - repository:
      name: org-name/bird-repo
    directory: birds
    subnav_name: my_subnav
  - repository:
      name: org-name/reptile-repo
    directory: reptiles
    subnav_name: my_subnav

subnavs:
  - name: my_subnav
    topics:
    - title: My Nav Section
      toc_path: birds/robins/index
      toc_nav_name: My Nav Overview
    - title: Other Nav Section
      toc_path: reptiles/index

Keys:

  • name: Defines name of the subnav, to be used to associate to sections in config
  • topics: Top-level items for subnav
    • title: Human-readable name of the topic, to be included in subnav
    • toc_path: Where the topic's Table of Contents file is found in the final app, without file extension. Usually this will be /index
    • toc_nav_name: Human-readable name of the table of contents page to be included in subnav. If not provided, a link to the TOC will still be added to the nav with name specified in title.

There is also an optional top-level key in config.yml that allows for manual exclusion of elements when parsing the file at toc_path to populate submenu items. Any valid Nokogiri css selector may be passed as an exclusion.

subnav_exclusions:
  - .ignore-class
  - h2:contains("Table of Contents")

Example Table of Contents page:

The parser only looks for h2 and ul/ol li > a elements on the specified toc_file for generating the subnav. Additionally, elements with class '.nav-exclude' will be ignored, along with any elements specified in the config.yml's subnav_exclusions key.

An example Table of Contents file:

# Some Title

Some Introductory text

## Table of Contents

* [A Blue Generated Nav Item](./blue.html)

## Some Former H2

* [A Red Generated Nav Item](./red.html)

Generated JSON:

Upon binding, Bookbinder parses each of the toc_files specified in the config and specifies any h2s as unlinked subheaders and ol/ul with li + a as children navigation items. Topics will be added to the json file in first the order specified in the config, then in the order specified in the TOC file.

Bookbinder makes these subnav links available in a json format at /subnavs/<your-subnav-name>.json. It will have written the name of the file containing the links from subnav_template.erb at a data attribute called data-props-location on 'div.nav-content'.

An example of the json links using the config and TOC file included above:

{
  "links":
  [
  	{"text": "My Nav Section", title: true},
    {"url": "/birds/robins/egg/index.html", "text": "My Nav Overview"},
    {"url": "/birds/robins/egg/blue.html", "text": "A Generated Nav Item From Link"},
    {"text": "Some Former H2"},
    {"url": "/birds/robins/egg/red.html", "text": "Another Generated Nav Item From Link"},
    {"text": "Other Nav Section", title: true},
    {"url": "/reptiles/index.html", "text": "Other Nav Section"}
  ]
}

Code Snippets

<%= yield_for_code_snippet from: 'my-org/code-repo', at: 'myCodeSnippetA' %> inserts code snippets extracted from code repositories.

To delimit where a code snippet begins and ends, you must use the format of code_snippet MARKER_OF_YOUR_CHOOSING start OPTIONAL_LANGUAGE, followed by the code, and then finished with code_snippet MARKER_OF_YOUR_CHOOSING end: If the OPTIONAL_LANGUAGE is omitted, your snippet will still be formatted as code but will not have any syntax highlighting.

Code snippet example:

; code_snippet myCodeSnippetA start clojure
	(def fib-seq
   	  (lazy-cat [0 1] (map + (rest fib-seq) fib-seq)))
	user> (take 20 fib-seq)
	(0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 2584 4181)
; code_snippet myCodeSnippetA end

Archive Menu

Bookbinder allows you to specify a drop-down menu template for use in the navbar. This can contain links to PDFs or other archived versions of documentation. To specify a drop-down menu, add the archive_menu key in config.yml as follows:

  archive_menu:
    - v1.3.0.0
    - v1.2.0.0: my-pdf-repo/v1.2.0.0.pdf

The first key (e.g. v1.3.0.0) is available for use as a title in your navbar. You can configure the structure of the drop-down menu by creating a template in master_middleman/source/archive_menus/_default.erb.

Finally, to insert the archive menu, use the <%= yield_for_archive_drop_down_menu %> tag in the appropriate part of the navbar in your layout.erb.

Template Variables

Bookbinder allows you to define template variables by adding key-value pairs to the config.yml file for your book.

To use a template variable, add the key to a source file. When you then bind your book, Bookbinder replaces the key with the value defined in the config.yml file.

  • To define a new template variable, add the key-value pair to the template_variables section of the config.yml file.

    Example config.yml file excerpt:

      ...
      template_variables:
        app_domain: example.com
        my-app: < a href="http://my-app.example.org" >this link
      
  • To use a template variable, add the key (in <%=vars.MY-KEY%> form) to a source file.

    Example source file excerpt:

      I deployed my app to <%=vars.app_domain%>. You can see it by clicking <%=vars.my-app%>.
      

Partials

Bookbinder supports partials, reusable blocks of source material.

Create a partial by adding a file containing source material to a repo. The name of the file must start with an underscore.

To use the partial, use the name of the file without the starting underscore in the following code, and add this code to the source file where you want the partial to appear: <%= partial 'FILENAME' %>

Including Assets

Bookbinder also includes helper code to correctly find image, stylesheet, and javascript assets. When using <% image_tag ..., <% stylesheet_link_tag ..., or <% javascript_include_tag ... to include assets, Bookbinder will search the entire directory structure starting at the top-level until it finds an asset with the provided name. For example, when resolving <% image_tag 'great_dane.png' %> called from the page dogs/big_dogs/index.html.md.erb, Middleman will first look in images/great_dane.png. If that file does not exist, it will try dogs/images/great_dane.png, then dogs/big_dogs/images/great_dane.png.

Commands

Bookbinder's entry point is the bookbinder executable. It should be invoked from the book directory. The following commands are available:

bind command

Bookbinder's most important command is bind. It takes one argument on the command line: local or remote.

    bin/bookbinder bind local

will find documentation repositories in directories that are siblings to your current directory.

    bin/bookbinder bind remote

will find doc repos by downloading the latest version from git. Note that if any of the repositories configured as 'sections' are private, you should create an SSH key for Bookbinder from an account that has access to the section repositories.

You should ssh-add this key to give Bookbinder access to the repositories.

The bind command creates two output directories, one named output/ and one named final_app/. These are placed in the current directory and are overwritten each time you run Bookbinder.

Note: When Bookbinder binds DITA sections of your book, it only sends error messages to the screen. Use the --verbose option with bind to see the non-filter output.

The final_app directory

final_app/ contains Bookbinder's ultimate output: a Rack web-app that can be pushed to Cloud Foundry or run locally.

The Rack web-app will respect redirect rules specified in redirects.rb, so long as they conform to the rack/rewrite syntax. For example:

rewrite   '/wiki/John_Trupiano',  '/john'
r301      '/wiki/Yair_Flicker',   '/yair'
r302      '/wiki/Greg_Jastrab',   '/greg'
r301      %r{/wiki/(\w+)_\w+},    '/$1'

The output directory

output/ contains an intermediary state. This includes output/master_middleman, the final prepared directory that the bind script ran middleman against.

watch command

Bookbinder's command for live previews in development is watch. Its functionality is similar to bind local in that it only includes repositories stored on disk. It then watches the sections (not the book or layout repositories) for changes and runs a preview server that updates upon file save.

    bin/bookbinder watch

Note: CPU usage directly relates to the number of sections your book is watching. If you find that watch is running slowly, either use bind or delete unused local repositories.

punch command

For snapshotting books at specific point in time, Bookbinder provides the punch command. This command git tags your book, all sections specified in the config.yml, and the layout repo (if provided) at the current head of master.

It takes one argument on the command line: the name of the tag you'd like to add.

    bin/bookbinder punch <tag-name>

Note that in order to tag any remote repositories, you will require push access. If you have not already, you should create an SSH key and ssh-add the key for Bookbinder from an account that has push access to the repositories.

update_local_doc_repos command

As a convenience, Bookbinder provides a command to update all your local doc repos, performing a git pull on each one:

    bin/bookbinder update_local_doc_repos

Running the App Locally

cd final_app
bundle
rackup

This will start a rack server to serve your documentation website locally at http://localhost:9292/. While making edits in documentation repos, we recommend leaving this running in a dedicated shell window. It can be terminated by hitting ctrl-c.

Continuous Integration

CI for books

The currently recommended tool for CI with Bookbinder is GoCD.

CI Runner

You will want a build that executes this shell command:

    bundle install --binstubs
    bin/bookbinder run_publish_ci

This will bind a book and push it to staging.

Deploying

Bookbinder has the ability to deploy the finished product to either staging or production. The deployment scripts requires the Cloud Foundry command line interface (cf CLI).

Download the cf CLI from https://github.com/cloudfoundry/cli/releases. For more information and instructions, see the cf CLI documentation.

Setting up CF Apps

Each book should have a dedicated CF space and host for its staging and production servers. The Cloud Foundry organization and spaces must be created manually and specified as values for "organization", "staging_space" and "production_space" in config.yml. Upon the first and second deploy, bookbinder will create two apps in the space to which it is deploying. The apps will be named "app_name"-blue and "app_name"-green. These will be used for a blue-green deployment scheme. Upon successful deploy, the subdomain of cfapps.io specified by "staging_host" or "production_host" will point to the most recently deployed of these two apps.

Deploy to Staging

Deploying to staging is not normally something a human needs to do: the book's CI script does this automatically every time a build passes.

The following command will deploy the build in your local 'final_app' directory to staging:

    bin/bookbinder push_local_to_staging

Deploy to Production

Deploying to prod is always done manually. It can be done from any machine with the book project checked out, but does not depend on the results from a local bind (or the contents of your final_app directory). Instead, it pulls the latest green build from S3, untars it locally, and then pushes it up to prod:

    bin/bookbinder push_to_prod <build_number>

If the build_number argument is left out, the latest green build will be deployed to production.

Generating a Sitemap for Google Search Indexing

The sitemap file /sitemap.xml is automatically regenerated when binding. When setting up a new docs website, make sure to add this sitemap's url in Google Webmaster Tools (for better reindexing?).

Contributing to Bookbinder

Running Tests

To run bookbinder's rspec suite, install binstubs, then run the included rake task:

Once: bundle install --binstubs

Then at any time: bin/rake