1. Introduction

This guide has been provided by Red Hat to assist enterprise projects in collaborating with upstream communities on documentation. For Red Hat, this guide provides tips for evaluating a community to see if they are prepared for collaboration with an enterprise software team, communication guidelines, information about supported and unsupported tools, and guidelines for structuring git repositories.

In addition to recommendations for Red Hat documentation teams, this guide provides best practices, templates, and content recommendations to upstream communities. These suggestions inform communities on how to prepare for Red Hat writers to collaborate on documentation.

1.1. Overview

Customer Content Services (CCS) is a Red Hat team responsible for producing documentation for Red Hat customers. Because all Red Hat products have an upstream, or open source community version, it makes sense for CCS to use these upstream resources in developing guides for customers. Many programs use pieces of upstream content in the downstream documentation. This framework defines best practices for single-streaming your documentation.

In principle, single-streamed documentation will be worked on completely in the upstream and brought down to the Customer Portal wholesale. In some projects, this process eliminates the overhead of maintaining two separate repositories for documentation content. This framework guides you through the process necessary for deciding if a community is a viable single-stream partner, setting up your repositories, choosing the right tools, and more.

1.2. Contacts

Communicate with members of this community by signing up for our mailing list. To sign up send an empty email to ccs-upstream-subscribe@redhat.com. If you later want to unsubscribe, send an empty email to ccs-upstream-unsubscribe@redhat.com.

To report issues or request enhancements to the Community Collaboration Guide use the GitHub issues tool.

2. Contributing upstream

This is a set of guidelines for getting involved in an upstream open source documentation project. It is geared primarily towards people working for a downstream distributor, although many of the guidelines are useful for everyone.

The first step to get involved is to join the conversation. Open source teams communicate in many different ways, including mailing lists, IRC, Slack, and Telegram. Find out where documentation conversations are happening and join. For most projects, there is a documentation-specific mailing list. Sometimes, there is just a single development mailing list that includes documentation work. When you join a mailing list, it’s a good idea to send an email introducing yourself. Tell the team who you are and what ways you’re interesting in helping.

When trying to introduce changes, it is important not to come across as judgmental or condescending. An email that paints a team’s work as wrong or broken will often be ignored, or it will cause people to become very defensive. Instead, point out the positive and try to show how it can be incrementally improved.

Be curious and show that you’re listening. If there’s something you don’t think is optimal, try to understand why it is the way it is. "This isn’t the right way to do things" rarely effects positive change. "I’m trying to understand why we do things this way" is a better way of sparking constructive conversation.

You may have specific ideas of how you want to improve something, but when working with the community, you have to be prepared to adapt your ideas to what others are saying. Every project has unique objectives, constraints, history, and culture. One size rarely fits all.

When proposing changes, focus on how they will benefit the project and the community, rather than how they will benefit you or your employer. Commercial distributions have business needs, and these affect what they would like to see in upstream projects. But their business needs aren’t necessarily interesting or relevant to the project.

Proposals to change things carry more weight when somebody is offering to do the work. You may have heard responses like "show me the code" or "patches welcome". If you want something improved, show that you’re willing to put in some of the work. If you’re not sure how you can best help, ask the community. "How can I help?" is a great question. If it involves technical work you’re not comfortable with, find somebody who can help.

Sometimes it can be difficult for a newcomer to propose new ideas in an established community. If you’re uncomfortable, or if you’re not making progress, try to find somebody more established in the community to talk to. Remember that the same advice applies when talking to an individual. Be positive and curious. Listen and understand. Offer to help.

Finally, be prepared to accept that things will not always go the way you want. One of the defining characteristics of a community is that it makes its own decisions. That’s the reality of being good open source citizens.

3. Evaluating upstream communities

Before joining an upstream documentation community with the goal of collaborating, you should gather data about the community to evaluate how your documentation team will fit in with the community’s.

3.1. Community readiness survey

This sample communication survey can be used to determine if single-streaming documentation is feasible on a specific project. Content Strategists and Documentation Program Managers will work together to gather data to evaluate community documentation for their products. Using the results of this survey your team will be able to make a proposal for or against single-streaming documentation.

The top possible score on this evaluation is 100 and the bottom score is 50.

Question to ask communities Answers & Weight

What is the product?

text

What is the community we’re evaluating? (allows for us to answer this survey multiple times - one for each community)

text

Is there a separate doc repo, or is it stored with the code (small vs larger projects)?

Docs in their own repository (5) | Docs part of code repository (4) | Docs not in a repository (5)

Are there written instructions for how to contribute?

Yes, detailed (5) | Yes, a few (4) | Yes, but they’re not followed (3) | No (1)

Are they open to having a company help in decision making?

Yes (10) | No (0)

Are they interested in the support of a content strategist (describe what one does; some communities want support along the lines of "editor")?

Yes (10) | No (5)

Who approves commits?

The committer (1) | A doc manager (3) | A select few community members (5)

Is there a style guide (follow up with do they use it?)?

Yes, detailed (5) | Yes, but not very detailed (4) | Yes, but it is not followed (3) | No (2)

 — If no, do they want one?

Yes (5) | No (3)

Are there formal documentation meetings?

Yes (5) | No (5)

What markup language are the docs written in?

Asciidoc (5) | Docbook (5) | RST + Sphinx (3) | Markdown (3) | Proprietary format (1)

Can anyone join the documentation team?

Yes (5) | No (2)

 — If yes, is there some sort of set criteria to join?

text

Is there a voting process to accept new active community members?

Yes (5) | No (5)

How are decisions in the community made? Consensus or Management?

Consensus (5) | Management (4) | Other

 — Enter the other

text

Is there a process for training newcomers?

Yes (5) | No (3)

Are community releases on the same schedule as product releases?

Yes (5) | No (3)

Are there formal community meetings?

Yes (5) | No (4)

Is there a documentation manager/lead?

Yes (5) | No (5)

 — If yes, is there a way for one of our CCS folks to run for this role?

Yes (5) | No (1)

What tools are used in creating documents?

Asciidoctor (5) | Gitbook (1) | RST + Sphinx (3) | Jekyll (3) | Confluence (1) | Other wiki (1) | HTML (1)

Average number of commits a month to code

number

Average number of commits a month to docs

number

4. Creating a new repository

If you are working on a completely new open source project you might need to create a git repository from scratch. A common option for creating a public repository is to use GitHub.

4.1. Setting up the repository

4.1.1. Prerequisites

To create a repository on GitHub you will first need to have an account.

4.1.2. Procedure

There are several ways to create a new repository in GitHub. One procedure is to:

  1. Log in to GitHub

  2. Click the plus (+) sign in the top right

  3. Choose New Repository

  4. Provide a Repository Name, Description, and choose if the repository is Public or Private

  5. Click Create Repository to finalize the process

4.1.3. Synchronization methods

The following synchronization methods are currently recommended:

4.1.4. Batch commit synchronization method

When to use this approach

The batch commit process is a good approach to use when you need to incorporate upstream content into product documentation and the product contains a good deal of additional product-specific content. In other words, when the upstream content is included as a subset of the product documentation.

Prerequisites

The batch commit method assumes that your upstream repository is hosted on GitHub and the machine where you run the batch commit script has the following utilities installed:

  • curl

  • zip

Directory structure

The batch commit example described here assumes that you have a book directory, my-sample-book, structured as follows:

my-sample-book/
|__ fetch-upstream.sh
|__ docinfo.xml
|__ master.adoc
|__ topics/
|__ upstream/

Where fetch-upstream.sh is the batch commit script (for details, see Sample batch commit script), and upstream is a subdirectory reserved for the upstream content.

Workflow

Given that you already have a batch commit script, fetch-upstream.sh, the workflow for synchronizing content from the upstream repository is as follows:

  1. Pull down the latest content from the upstream repository and put the downloaded files in the upstream/ subdirectory:

    $ ./fetch-upstream.sh
  2. Inspect the downloaded content (for example, using git diff) to check for new files, restructured content, and so on. If necessary, edit the book file, master.adoc, to incorporate new content.

  3. Add and commit the downloaded content:

    $ git add upstream
    $ git commit -m "Synched content from upstream"
Sample batch commit script

The batch commit script, fetch-upstream.sh, is a simple bash script that pulls down the latest upstream content, copying the relevant upstream files into the upstream subdirectory. The script exploits a particular feature of GitHub, whereby GitHub provides a downloadable archive file containing the working tree for any branch in the repository. The archive file has a snapshot of the latest content in a particular branch and thus provides an ideal basis for synchronizing content downstream.

To see how this works, consider the following sample fetch-upstream.sh script developed for synchronizing the contents of the Apache Camel Component Reference:

#!/bin/sh

branch=camel-2.18.x (1)

echo "info: fetching upstream content from branch: $branch"
echo

# -L = follow redirects
curl -L -o $branch.zip https://github.com/apache/camel/archive/$branch.zip (2)

# -o = overwrite, -j = flatten directory structure, -q = quiet
unzip -qjo -d upstream $branch.zip camel-$branch/components/camel-*/src/main/docs/*.adoc (3)
unzip -qjo -d upstream/images $branch.zip camel-$branch/components/camel-*/src/main/docs/*.png
unzip -qjo -d upstream $branch.zip camel-$branch/camel-core/src/main/docs/*-component.adoc

rm $branch.zip (4)
  1. Set the branch variable to the name of the upstream branch.

  2. Download the archive (.zip) file from GitHub, which includes a snapshot of the latest content from the $branch branch and store it locally as the file, $branch.zip.

  3. Extract the relevant documentation files from the archive and put them into the upstream subdirectory. Note that the unzip command is a remarkably flexible tool for extracting content from the archive. In this particular case, the AsciiDoc files are embedded in the Java code base and scattered across hundreds of subdirectories. But thanks to the globbing capabilities of unzip, it takes only a few commands to find and extract all the relevant files.

  4. Clean up by removing the downloaded archive, $branch.zip.

Note
It is not necessary for the script to figure out whether specific files have changed or not. Git automatically detects when a file has changed based on the file’s content, not its creation time. So Git ignores any files with the same content as before.
Pros and cons

Given the simplicity of the batch commit script, you might get the impression that it is not as powerful as other approaches. But if you compare it with a mechanism that provides similar functionality — for example, Git submodules — it measures up well. Comparison of batch commit and git submodule makes a point by point comparison of the batch commit process against the Git submodule process.

Table 1. Comparison of batch commit and git submodule
(Negative) Feature Batch commit Git submodule

Contributor needs to know special processes or commands?

No

Yes

For example, git submodule update

Requires customization of publication toolchain?

No

Yes

Causes repository bloat?

No

Only the required files are committed to the downstream repository.

Yes

Complete working tree and complete history are downloaded.

Requires maintenance to keep in sync?

Yes

Yes

5. Migrating an existing repository

If you are working on an existing open source project where there is an established downstream documentation team and an established upstream community, you might need to migrate existing content from the downstream repository to the upstream repository so that it can be shared across both repositories. This chapter outlines how to migrate content from a downstream repository to an upstream repository.

5.1. Planning the migration

If you need to migrate content from an existing downstream repository to an upstream repository, it is important that you plan these efforts. Planning should be a collaborative process between a representative of the downstream documentation team and the upstream community, and might require the building of a new relationship.

Use the planning process to discover and decide upon important details about the migration. For example, who are the main contacts in the downstream documentation team and the upstream community, what will the new workflow be, and how will changes to existing titles and development of new titles be handled when the content has been fully migrated and the new workflow put in place?

Most importantly, the downstream documentation team and upstream community must reach a common understanding about the key goals of the migration and how both parties will interact when the migration is complete. This might require participation in community meetings and holding workshops with the downstream documentation team to take them through the new workflow and communication guidelines.

5.2. Migration checklist

The following is a basic checklist of considerations to make before migrating content from an existing downstream repository to an upstream repository. In principle, the content should be laid out in accordance with one of the structures outlined in Project Structure.

Where will you submit the content?

Is there a dedicated upstream repository for documentation, or will the content be managed alongside the code? Alternatively, does a new upstream repository need to be created for documentation, and if so, who will perform this work?

How will you submit the content?

When the content is ready, how should it be submitted to the upstream community? Can a standard pull request be submitted that adds all the content at the same time, or is there a different process?

When will you submit the content?

Can the content be migrated at any time, or should it be migrated in line with an existing milestone such as an upstream community release? Who should be notified when the content has been migrated, and when will any new workflows commence? How will changes to the documentation be handled in the time after a pull request to submit the content has been created and before it has been accepted?

Do you have the required permissions?

The members of the downstream documentation team must be granted the permissions and roles to work on the content in the upstream repository before any new workflows commence. Before requesting that any permissions or roles be granted, all members of the downstream documentation team must create an account on the appropriate website, if required.

Have all brand-specific references been conditionalized?

If there are any references to resources that are inappropriate for or cannot be accessed by the upstream community, such as support statements or links to content on the Customer Portal, this content must be conditionalized so that it only appears in the downstream version of that content. Likewise, if there are any references to resources that are inappropriate for the end users of the downstream documentation, such as links to community documentation, this content must be conditionalized, so that it only appears in the upstream version of that content.

Have all product names and versions been converted to attributes?

If there are any references to product names or product versions that are specific to the downstream community or upstream community, and have an equivalent in the other, ensure they are replaced with attributes, so that the correct product names and product versions will be input when the content is built. See AsciiDoc Attributes for more information.

How will you manage existing titles?

Is there any content in the upstream repository that must be retired or included in the new content being added? If so, a decision must be made as to whether this content will be kept separate or whether it will be converted into a similar format as the other content.

What license is applied to the content?

If there is any existing content in the upstream repository, what license is applied to that content? If the same license is applied to all content in an upstream repository or to all rendered documentation on a community website, it is important to discuss how and where this license is applied, and to discuss whether any conditions would prevent that content from being used by both the upstream community and downstream documentation team.

What markup language is required?

If there is any existing content in the upstream repository, what markup language was used to write that content, and what rendering and publication mechanism is used to convert it into readable documentation? Is it possible to use AsciiDoc as the markup language, and if not, how can content to be synchronized with the downstream repository be converted from the current markup language into AsciiDoc?

How will you synchronize content?

After the content has been migrated to the upstream repository, how will that content be synchronized with the downstream repository? Do any titles exist only in the upstream or in the downstream? If so, consider using the Batch Commit method to synchronize only selected content. If all content in the upstream repository can be synchronized as is with the downstream repository, consider pushing all branches from the upstream repository to the downstream repository as a second remote. If the method used to synchronize content affects the way the content is to be managed in the upstream community (for example, references to downstream-only resources must be included, even if conditionalized), the potential impact must be discussed with the community.

6. Project structure

There is no single structure that will work for all projects; rather as a project grows and becomes more complex, it is likely to move through a variety of different structures. The repository structure may change as files and directories are added, a large repository may split into separate, related repositories, etc. As a project grows, documentation needs for the project also grow. And just like you want to have a plan for project architecture that changes and adapts as the project grows, you likewise want to have a plan for the documentation structure that grows and adapts as the doc set grows.

This section discusses repository and directory structure and how to structure your content for ease of reuse (both in multiple documents and in upstream/downstream documents).

6.1. Repository and directory structure

The first steps towards documenting a project are often found in the README file of the repository. Eventually the project will grow to where there is a need for more documentation than you can fit in a single README, and that may appear in the form of a project wiki, a separate installation guide, possibly a developer guide, and one or more user guides. You may start out with all of the documentation in the same repository as the code, but as things grow more complex, you may want to consider having a separate repository for your documentation. This makes it easier for community members who may only want to contribute to the documentation, as they don’t have to worry about merge conflicts in the code. For more information about considerations when sharing a repository with engineering, see Considerations for sharing a repository with engineering.

As your project grows, you should consider the structure you want to use for your documentation directory. Directories should be structured in a logical and related fashion. Many projects have a documentation repo or directory for their project web page, and possibly a separate repo or directory for the project documentation. You may choose to have separate repositories for each “manual” or you may choose to have all the documents in your doc set share a repository. Contribution style and build requirements are two primary considerations when you decide how to proceed.

Add a docs directory to the code repository.

This makes it easier for developers to update the documentation, but may present a challenge for non-developers who want to contribute to the documentation but may have difficulties following the repository workflow used by developers.

Add a new repo for each new title or document.

The single title per repository model allows independent updates between titles, but prevents topic sharing among titles.

Add a new repo with multiple titles or documents.

The multiple title per repository model enables simple-and-easy topic sharing between titles, but does require building all titles when updates are made.

6.2. Flat file structure

In a flat file structure, there are no sub-directories, just one directory with all the documentation files in a single directory. A flat file structure might be as simple as a single README file, or contain a complete guide. A flat file structure for an AsciiDoc guide might look something like this:

├── README.adoc
├── documentation
├──|── master-docinfo.xml
├──|── master.adoc
├──|── attributes.adoc
├──|── logo.png
├──|── screenshot1.png
├──|── screenshot2.png
├──|── screenshot3.png
├──|── topic-1.adoc
├──|── topic-2.adoc
├──|── topic-4.adoc
├──|── topic-5.adoc

In a flat file system, every file must have a different name because there is only one list of files. A flat file structure may work with a very small number of files, but once a documentation project becomes more complex, it becomes more difficult to have all the files in the same directory. And that is when the documentation for a project may require a more complex structure.

6.3. Single-book structure

If you do not share any content between books, you may choose a single book per directory structure. A structure with a single AsciiDoc guide per repository might look something like this:

├── README.adoc
├── docs
│   ├── DocumentTitle
│   ├──-|──  topics -> ../topics/ (symlink to docs/topics/)
│   ├──-|── master-docinfo.xml
│   ├──-|── master.adoc   (book file/table of contents for the documentation)
│   │   ├── /topics  (all topic files for the documentation)
│   │   │   ├──  /images (all images for the documentation)
│   │   │   │    ├── logo.png
│   │   │   │    ├──screenshot1.png
│   │   │   │    ├── screenshot2.png
│   │   │   │    ├──screenshot3.png
│   │   │   ├── attributes.adoc (variables file)
│   │   │   ├── topic-1.adoc
│   │   │   ├── topic-2.adoc
│   │   │   ├── topic-4.adoc
│   │   │   └── topic-5.adoc
└── scripts (Scripts to automatically create and build documentation)
    └── buildGuides.sh

6.4. Multiple-book structure

If you have common files that you want to reuse between books, you may choose a more complex directory structure, where all the books live in the same repository and have access to common files.

Note that in the following multiple-book structure, each “book” directory has a symlink to a common directory for topic files. This allows you to use any individual topic in any book, saving time writing and updating topics that appear in more than one place. This structure also uses a common directory for images inside the topics directory, again allowing for the reuse of images such as button icons and product logos. And the attributes file is also common, allowing for the same replacement variables in all files and books.

A structure with multiple AsciiDoc guides per repository and a single topic directory might look something like this:

├── README.md
├── docs
│   ├── Title_A
│   │   ├── master.adoc
│   │   ├── master-docinfo.xml
│   │   ├── topics -> ../topics/ (symlink to docs/topics/)
│   ├── Title_B
│   │   ├── master.adoc
│   │   ├── master-docinfo.xml
│   │   ├── topics -> ../topics/ (symlink to docs/topics/)
│   ├── Title_C
│   │   ├── master.adoc
│   │   ├── master-docinfo.xml
│   │   ├── topics -> ../topics/ (symlink to docs/topics/)
│   ├── topics (all topics for titles)
│   │   │   ├── images (all the images for titles)
│   │   │   |   ├──  logo.png
│   │   │   |   ├──  screenshot1.png
│   │   │   |   ├── screenshot2.png
│   │   │   |   ├── screenshot3.png
│   │   │   ├──attributes.adoc (variables file)
│   │   │   ├── topic-1.adoc
│   │   │   ├── topic-2.adoc
│   │   │   ├── topic-4.adoc
│   │   │   └── topic-5.adoc
│   │   │   ├── topic-shared-1.adoc
│   │   │   ├──  topic-shared-2.adoc

And a structure with multiple AsciiDoc guides per repository and multiple topic directories might look something like this:

├── README.adoc
├── docs
│   ├── title-a
│   │   ├── enterprise
│   │   │   ├── master-docinfo.xml
│   │   │   ├── master.adoc
│   │   │   └── topics -> ../topics
│   │   ├── topics
│   │   │   ├── shared -> ../../shared
│   │   │   ├── topic-1.adoc
│   │   │   ├── topic-2.adoc
│   │   │   ├── topic-4.adoc
│   │   │   └── topic-5.adoc
│   │   └── upstream-1
│   │       ├── master-docinfo.xml
│   │       ├── master.adoc
│   │       └── topics -> ../topics
│   ├── title-b
│   │   ├── enterprise
│   │   │   ├── master-docinfo.xml
│   │   │   ├── master.adoc
│   │   │   └── topics -> ../topics
│   │   ├── topics
│   │   │   ├── shared -> ../../shared
│   │   │   ├── topic-1.adoc
│   │   │   ├── topic-2.adoc
│   │   │   ├── topic-4.adoc
│   │   │   └── topic-5.adoc
│   │   └── upstream-1
│   │       ├── master-docinfo.xml
│   │       ├── master.adoc
│   │       └── topics -> ../topics
│   └── shared
│       ├── attributes.adoc (variables file)
│       ├── images (all images for titles)
│       ├── templates
│       │   └── revision-info.adoc
│       ├── topic-shared-1.adoc
│       └── topic-shared-2.adoc
└── resources
    ├── asciidoc-writing-guide.adoc
    └── scripts
        └── buildGuides.sh

6.5. Considerations for sharing a repository with engineering

If you are considering sharing a repository with engineering, that is, for the software code and documentation to reside in the same upstream repository, here are a few things you will want to keep in mind.

Space considerations

The size of the combined repository will be large, so if limited space is an issue, keep this factor in mind.

Rebase often

When working in the same repository as engineering, rebasing frequently is often a necessity because engineering is making changes too. Before making any changes to the documentation you’ll want to rebase your fork.

Upstream shared repository branches and downstream docs repository branches

Although you’ll be sharing the upstream repository with engineering, you’ll also need a downstream docs repository. Since more than likely the upstream repository branching structure will not match exactly the downstream docs repository branching, you will need to sync up the content.

Also, investing the time to plan a branching strategy in advance will save plenty of headaches in the long run.

Use the git export script

To easily sync up content, use the git export script.

Use attributes

In general, using attributes will facilitate ease of use between upstream docs and downstream docs. One of the most useful is for the product name itself: {ProductName}. Other useful attributes include those for any version numbers used in the docs or any other product names. For more general information about how to use attributes, see AsciiDoc attributes.

In particular, using a variable for the upstream directory in the downstream docs repository is helpful. For example, define the following variable in the downstream docs repository attributes file:

:UpstreamDir: upstream/documentation

Then, in the downstream master.adoc files, use the variable in the include statements:

include::{UpstreamDir}/assemblies/assembly-installing.adoc[leveloffset=+1]

6.6. Content structure

Rather than writing your documentation in a single lengthy file, a best practice is to break the content up into small chunks. There are several reasons why this is a good idea. Having some sort of structure for your content provides many benefits for both readers and writers of your documentation:

  • Onboarding new contributors – It’s easier for new contributors to add to the documentation if they have some sort of template or pattern to follow. For example, all UNIX/LINUX man pages follow a similar structure, so when a developer is documenting a new command, they can follow that familiar pattern.

    A commonly used pattern for documentation is to chunk content into one of three types of topics:

    • Procedure or Task – The ordered steps to complete a task or perform an action using the software.

    • Concept or Overview – Product-specific terminology or concepts that the user needs to understand in order to successfully use the software.

    • Reference – Reference material about the software, for example configuration settings , lists of commands, or API documentation.

  • Reusability – If you write content in small chunks, it can be reused in different documents that cover the same topics. For example, topics such as “System Requirements” or “Supported Platforms” might appear in Release Notes, planning documentation, and installation documentation.

  • Findability – Content that is properly structured makes it easier for readers to find answers to their questions. For example, when procedures are properly formatted as numbered steps, readers don’t have to search paragraphs of text for instructions for how to complete a task. Projects that follow naming conventions and have an organizational structure make it easier for contributing writers to find and update topics.

  • Organization – Writing content in small chunks makes it easier to rearrange content than when writing content in longer files.

See the Modular Documentation Reference Guide prepared by Red Hat for guidance on authoring documentation using a modular structure.

In general, when writing content you want to use simple language and avoid jargon that people unfamiliar with your project might not understand. Writing short sentences and short paragraphs also makes your content easier to read and understand.

6.7. File naming

No matter what repo and directory structure you choose, directory and file names should be clear and consistent.

  • Numbered file names like 52187.adoc or IMG_390.png are more likely to cause confusion for other contributors.

  • Short file names are good, as long as they’re still meaningful. But give enough detail to make the content clear (overview.adoc could be anything).

  • Long file names are often unwieldy, hard to work with, and easy to mistype. Try to find the right balance for file-name length.

  • File names should reflect the topic they cover to help contributors find content in your files.

  • Do not include the project or product name, book name, release version, or anything similar in file names.

  • Do not hard-code file names when linking documents. Use relative paths to the topic or directory.

7. AsciiDoc

AsciiDoc is a text document format that you can use to write documentation, articles, books, web pages, and blogs. AsciiDoc files can be translated to many formats including HTML, PDF, EPUB, and man page.

The Red Hat documentation team uses Asciidoctor as part of the publishing toolchain.

7.1. AsciiDoc attributes

AsciiDoc attributes are variables you can use in common files to:

  • avoid hard-coding brand-specific information,

  • share content between multiple brands more easily.

To use attributes:

  1. Set them in the relevant brand AsciiDoc attribute file in the common directory.

  2. Include the brand AsciiDoc attribute file in the master.adoc file for the relevant document:

    include::attributes.adoc[]
  3. Replace brand-specific terms with the variable names that you have defined, and use ifdef statements to mark blocks of brand-specific content.

Common AsciiDoc attributes include product name, abbreviated product name, and product version. For more information about attributes and ifdef statements, see Attributes and Conditional Preprocessor Directives in the Asciidoctor User Guide.

The example below creates attributes for the Community Documentation brand.

  1. Create a new community.adoc file in the common/attributes/ directory.

  2. Open the file, and add your attribute mappings, each entry on a new line:

    :product-name: Community Documentation
    :product-name_short: Community
    :product-name_abbr: cd
    :product-version: 1.0
  3. Save the file.

  4. In each doc-Guide_Name/community directory, edit the master.adoc file. Include the attribute file, and add the variable name you want to use to identify ifdef statements:

    include::common/attributes/community.adoc[]
    
    :community:
  5. Anywhere in a common topic file that you would normally use the product name or version, use the following values instead:

    {product-name}
    {product-name_short}
    {product-name_abbr}
    {product-version}
  6. Anywhere in a common topic file that you need a section of text to appear only in the Community Documentation version of the guide, use an ifdef statement:

    // An ifdef for an entire sentence or paragraph
    ifdef::community[]
    This is a sentence that applies only to the Community Documentation version of the document.
    endif::community[]
    
    // An ifdef for an inline reference, which includes an entry for another brand
    See
    ifdef::community[the Community Standards Guide.]
    ifdef::productx[the Product X Conventions Guide.]

    The ifdef statement must be at the start of a new line, even for inline references. When the Community Documentation version of the guide is rendered, the content inside the ifdef statements for community will appear, and the content inside the ifdef statements for productx will be excluded. Any content not included inside an ifdef statement will appear in rendered guides for all brands.

  7. Render the guide to verify that your attributes are appearing correctly. Navigate to the directory containing the master.adoc, and use:

    asciidoctor compile

In addition to storing product names and versions, attributes can be used to store book-local and cross-book links for your guides. Doing this allows you to:

  • construct consistently structured and predictable link URLs (especially when combined with explicit ID anchors),

  • single-source your link URLs, making updates easier,

  • eliminate the risk of introducing errors when updating your links.

To store a relative link as an attribute, you must define it in the:

:link-getting-started: /docs/getting-strated.html

Attributes can also store external link URLs, allowing you to update them without breaking any links in your guide.

:link-community-docs: https://docs.example.com/guides/community.html

Use the variable in a link macro. The variable will automatically resolve to the URL stored in the attribute when you build your documents.

link:{link-community-docs}#introduction[Community Documentation Introduction]

To force your links to open in a new window:

  1. Set the linkattrs attribute in your attributes.adoc file:

    :linkattrs:
  2. Use the caret ^ character to enforce the target=_blank HTML attribute for the link anchor.

    link:{link-community-docs}[Community Documentation^]
  3. Alternatively, you can set the the AsciiDoc attribute explicitly:

    link:{link-community-docs}[Community Documentation, window="_blank"]

    When clicked, the link will always open in a new tab.

7.3. Previewing your content

7.4. AsciiDoc converters

If your project is not already written in AsciiDoc and you want to migrate from Markdown or another markup language, there are a variety of conversion tools available.

  • The Atom editor has a package to convert Markdown to AsciiDoc.

  • There is a plugin to convert Google docs to AsciiDoc.

  • Pandoc can convert between a large number of different markup and file formats including DocBook, Emacs Org-Mode, EPUB, HTML, LaTeX, LibreOffice ODT, Markdown, MediaWiki markup, Microsoft Word docx, OPML, reStructuredText, textile, TWiki markup, and Txt2Tags.

  • rst2adoc is an AsciiDoc builder and writer for Sphinx that allows you to convert reStructuredText (RST) files to AsciiDoc using the Sphinx build system.

8. Building content

Writing your documentation using AsciiDoc means that you can build HTML, PDF, EPUB, and man pages. During the writing process, you build your documentation to test and review the content as described in Rendering content locally with Asciidoctor.

Depending on the complexity of the documentation, you might also decide to adopt a tool other than AsciiDoctor to help you organize the building of documentation sets. Some commonly used tools are described later in this section.

8.1. Rendering content locally with Asciidoctor

When your source content is ready to be reviewed or published, you can render it into a display format that can be hosted on a website, included directly in a product, or otherwise accessed by your users. The recommended tool for rendering AsciiDoc into a display format is Asciidoctor. Asciidoctor is a fully open-source, Ruby-based implementation of AsciiDoc, and is also the tool that GitHub itself uses to render the content of files written in AsciiDoc.

See the project home page for instructions on how to install Asciidoctor on a variety of platforms:

The following is the basic syntax for rendering content into a display format:

$ asciidoctor master.adoc

This command creates a single HTML file of the same name and in the same directory as the specified master file. The master file does not need to be in the current working directory, and you can specify either a relative path or absolute path to it.

In addition to this basic syntax, Asciidoctor also provides a number of options that allow you to customize the location and format of the content that it renders.

The following example outlines how to specify a custom output directory:

$ asciidoctor -D ./output master.adoc

The following example outlines how to render the content as an article instead of as a book:

$ asciidoctor -d article master.adoc

For additional examples, including instructions on how to render content in formats other than HTML such as PDF, EPUB3, and LaTeX, see How do I render a document? on the AsciiDoctor project home page.

8.2. AsciiBinder

AsciiBinder is a Ruby-based command-line tool that is designed to streamline the documentation and publication process for teams that manage a large volume of content and re-publish that content regularly. AsciiBinder allows you to share content across multiple distributions by using a map of content that is common to all distributions and by breaking the metadata for each distribution out into a separate branch in Git.

Advantages
  • Stable

  • Simple to use

  • Low barrier to entry

Challenges
  • Support is provided on an ad-hoc basis

  • Uses a fixed directory structure defined by AsciiBinder

8.3. GitBook

GitBook is a documentation hosting system based on GitHub.

Advantages
  • Very low barrier to entry for community members

    • Easy to make edits

    • Comes with a built-in stylesheet

  • Publishes in AsciiDoc

  • Integrates into GitHub

  • Allows inline comments

  • Supports building books written in multiple languages

    • Each language is in a subdirectory

    • Support for rtl languages

  • Includes a full-text search engine

    • JSON index file on a static version of the documentation

Challenges
  • Having to review inline comments is time consuming when you are also monitoring issue tracking systems

  • Converting to downstream requires a Python script

  • Requires a lengthy process to pull content from GitBook to the downstream

  • Directory tree defined by GitBook and does not allow for easy manipulation

  • Only free for a small number of managers, has a cost after that

  • Things that work in AsciiDoc do not always work in GitBook

    • Certain special tags will completely break things in GitBook

    • AsciiDoc is not fully supported in GitBook

  • GitBook requires that we use a JSON file for attributes which is not as flexible as AsciiDoc

    • You can embed attributes in AsciiDoc, but not in JSON

  • GitBook support is ad-hoc

  • Edits are immediately committed

  • Editor is not advanced enough to keep in conditional tags in place

8.4. Hugo

Hugo is a static site generator written in Go.

Advantages
  • Hugo is built using Go — a compiled language — and installing or updating Hugo is as simple as downloading a binary and setting up your system to use it.

  • You can install Hugo on Linux, macOS, and Windows.

  • Hugo has extensive documentation.

  • Hugo is a very popular static site generator and has an active developer community.

Challenges
  • Uses a fixed directory structure defined by Hugo. In Hugo, there’s only a single content directory. Hugo also assumes that the same structure that organizes your source content is used to organize the rendered site.

  • Hugo does not come with a default theme, you must set one up before you can view your content. However, there are many themes available on the Hugo web site.

  • The Hugo documentation tends to be technical and developer/features focused, rather that writer/task focused.

8.5. RST with Sphinx

reStructuredText (RST) is a popular lightweight documentation format used by many, particularly Python-based, projects and open source communities. RST is often used alongside the Sphinx documentation generator, which can be seen as an counterpart of the AsciiDoctor toolchain for AsciiDoc.

Advantages
  • The toolchain of choice for a large number of open source projects.

    • Easy to find community support, resources and examples.

  • Supports translations with gettext, has been integrated with Zanata.

  • Supports multiple output formats, including HTML, HTML single, PDF, ePub, Texinfo, man pages, etc.

  • Fully customized document hierarchy, design themes, etc.

  • More features can be added with custom extensions.

  • Supported by popular community hosting services, such as Read the Docs.

Challenges
  • Does not provide native integration with AsciiDoc-based toolchains.

    • Extensions or converters must be used to build or convert RST to AsciiDoc. For details, see AsciiDoc converters.

9. Publishing content

To be useful, content must be published to a public location that end users can access. There are multiple ways to publish. Some commonly used tools are described in this section.

9.1. AsciiBinder

In addition to providing a system to structure and maintain documentation for multiple brands using a single repository, AsciiBinder also provides the ability to preview and package documentation as a set of HTML files that you can publish on a website.

Run the following command to build a preview of the documentation:

$ asciibinder build

The output of this command is saved in the <docs_repo_dir>/_preview/<distro>/<branch_dir_name> directory.

Run the following command to package the documentation:

$ asciibinder package

The output of this command is saved in the <docs_repo_dir>/_package/<distro>/<branch_dir_name> directory. Each sub-directory in the _package represents the website content for a single brand, and can be copied to a hosting server as is.

9.2. Using Travis CI and Asciidoctor container to publish to GitHub Pages

This publishing mechanism uses a single configuration file, .travis.yml, and is based on a GitHub + Travis CI + Asciidoctor container + GitHub Pages toolchain, an idea taken from GitHub Pages Deployment.

Each commit pushed to a pre-configured branch (such as master, devel, or stable) containing a .travis.yml automatically triggers a document build, so you do not need an extra tool installed locally in order to publish an update to the document. When the Asciidoctor container running in Travis CI successfully finishes the build, Travis CI pushes the resulting HTML (and, optionally, PDF) to a deployment branch (such as gh-pages or publish), and GitHub Pages then publishes the HTML (and PDF) from the deployment branch to the desired URL (for instance, my-project.github.io/my-document).

This publishing mechanism is used to publish the Community Collaboration Guide from https://github.com/redhat-documentation/community-collaboration-guide.

9.2.1. Sample .travis.yml

Below is a sample .travis.yml file that must be placed in the root directory of your branch, from which you want to publish to GitHub Pages.

sudo: required

branches:
  only:
  - master # Branch from which to publish

services:
  - docker

before_install:
  - mkdir -p output
  - docker pull asciidoctor/docker-asciidoctor

script:
  - docker run -v $TRAVIS_BUILD_DIR:/documents/ --name asciidoc-to-html asciidoctor/docker-asciidoctor asciidoctor --destination-dir=/documents/output --out-file=index.html community/master.adoc
  - docker run -v $TRAVIS_BUILD_DIR:/documents/ --name asciidoc-to-pdf asciidoctor/docker-asciidoctor asciidoctor-pdf --destination-dir=/documents/output --out-file=community-collaboration-guide.pdf community/master.adoc

after_error:
  - docker logs asciidoc-to-html
  - docker logs asciidoc-to-pdf

after_failure:
  - docker logs asciidoc-to-html
  - docker logs asciidoc-to-pdf

deploy:
  provider: pages
  skip_cleanup: true
  github_token: $TOKEN # Set in travis-ci.org dashboard
  local_dir: output
  on:
    branch: master

10. Contributing to the guide

You can contribute to this project in two ways:

  • Propose changes to the Community Collaboration Guide

  • Update the Community Collaboration Guide

Subsequent sections provide details for conducting each activity.

10.1. Proposing a change to the guide

Currently, the best method for proposing a change to the Community Collaboration Guide is to open an issue in the community-collaboration-guide GitHub repository.

Prerequisites

You must be a member of the GitHub community-collaboration-guide repository. Request to join by emailing your GitHub username to ccs-upstream@redhat.com.

Procedure
  1. Navigate to the Issues tab and click New issue. The window for creating a new issue is displayed.

  2. In the Title field, type a concise summary of the Guide change you are proposing.

  3. In the Write field, provide additional details, such as the "what, where, and why" of the modification.

  4. Attach any files, such as screen captures, that help illustrate your proposal.

  5. (Optional) Navigate to the Preview tab to review your submission.

  6. Click Submit new issue. The title and number of your open issue are displayed in a new window.

10.2. Updating the community collaboration guide

We encourage contributions to the Community Collaboration Guide. In particular, you can share your experiences in the following areas:

  • Evaluating communities

  • Working through the communications process

  • Using supported (and unsupported) tools

  • Structuring repositories in new and different ways

  • Exploring best practices and discovering lessons learned

Prerequisites
Procedure
  1. Navigate to the Issues tab and click on the Title of the issue you’d like to address.

  2. Assign the issue to yourself so that others know you are working on it.

  3. Keep the issue up to date with your progress

  4. Submit a Pull Request (PR) with your edits

  5. Ask for a review from someone on the team

  6. Once your item is merged, close the issue.

Fork the upstream (GitHub) repository

Fork the community-collaboration-guide upstream repository to create a fork under your own GitHub ID. This allows you to work on multiple pieces of content and push changes to branches in your local GitHub instance. When you are ready, you can request the changes be merged from your local fork into the upstream repository.

  1. Open a browser and navigate to the upstream repository located at https://github.com/redhat-documentation/community-collaboration-guide.

  2. Click the Fork button located in the upper right, under your profile icon.

  3. Choose the location of the forked repository.

Related information

Add your SSH keys to GitHub

When using the SSH address for creating a clone, you need to add an SSH Key to GitHub. See the article Generating an SSH Key for more information.

Clone your fork to your local workstation

Clone the repository. Your fork is the origin location for your local files.

  1. Open a terminal and navigate to the location where you want to create a directory to contain your local copy of the repository.

  2. Type the following command:

    $ git clone git@github.com:USERNAME/community-collaboration-guide.git

    In this and subsequent examples, USERNAME represents your GitHub user ID.

  3. Navigate to the newly created community-collaboration-guide directory.

    $ cd community-collaboration-guide/

Add the upstream as a remote repository

After you have forked and cloned the upstream repository, connect it to your local fork by adding the upstream repository as a remote.

  1. List the current remote repositories:

    $ git remote -v
    origin	git@github.com:USERNAME/community-collaboration-guide.git (fetch)
    origin	git@github.com:USERNAME/community-collaboration-guide.git (push)
  2. Add the upstream as a remote repository and fetch its contents. This allows you to check out and work with the latest source.

    $ git remote add -f upstream git@github.com:redhat-documentation/community-collaboration-guide.git
  3. Enter your GitHub credentials if prompted to do so.

  4. Verify that the new remote was added:

    $ git remote -v
    origin  git@github.com:USERNAME/community-collaboration-guide.git (fetch)
    origin  git@github.com:USERNAME/community-collaboration-guide.git  (push)
    upstream  git@github.com:redhat-documentation/community-collaboration-guide.git (fetch)
    upstream  git@github.com:redhat-documentation/community-collaboration-guide.git (push)

Fetch the source and create a branch

Fetch the latest source from the upstream repository. Note that using the git fetch command to obtain the latest copy of the source does not actually "put" the content on your local fork until you perform some other action, such as creating a branch.

  1. Use the git fetch command to fetch the latest source from the repository:

    $ git fetch upstream
  2. Create a local working branch that is based on an upstream branch. The branch name should be descriptive, containing an issue number or short summary of the change.

    $ git checkout -b BRANCH_NAME upstream/master

    In this example, BRANCH_NAME is the unique name of the branch you are using to make changes locally.

Note

You can check out multiple topic branches and work on multiple features at one time with no impact on each other as long as each topic branch is branched from master.