
# Contributing Documentation to Beaker

## Documents

Beyond the usual README, Beaker has an ever-growing amount of written documentation including tutorials, recipes, and other helpful information (see [docs/](docs)). Changes larger than bug fixes will usually be required to include such user-friendly documentation.

## Style

User-friendly Documentation (tutorials, how-tos, etc.) uses [GitHub Flavored Markdown](https://guides.github.com/features/mastering-markdown/). We adopt the following conventions.

### Text

- Don't hard-wrap text blocks (including lists). There is disagreement about the ideal editor width, so don't hard-wrap text. Code blocks may be wrapped as appropriate.

### Lists

- Use `-` lists to avoid confusion with `*emphasis*`.
- Be sure to indent code blocks within list items.

### Headers

- Use Markdown Headers.
- Always place a blank line before and after headers.

### Code

- Use inline code for snippets (paths, file names, variables, partial commands, etc.)
- Use fenced blocks for code of one full line or greater
- Offset fenced blocks with whitespace before and after, except in list items.
- Mark the language of code blocks:
  ~~~
  ```console
    $ beaker --help
  ```
  ~~~
  Supported languages are documented [here](https://github.com/github/linguist/blob/master/lib/linguist/languages.yml). You will probably be using `console`, `ruby`, `puppet`, or `yaml` most of the time.
- It's nice to provide a shebang (`$`) in console examples to distinguish input from output.

## Inline

All inline/generated documentation uses [YARD](http://yardoc.org/). Below is an example usage, a quick summary of documentation expectations, and finally a short reference for those new to YARD.

They say a picture is worth a thousand words, hopefully this example will be worth more than the 154 it’s composed of:

```ruby
    #
    # @param  [Array<Host>, Host, #execute] hosts    The host(s) to act on
    # @param  [String]                      action   The action to perform
    # @param  [Hash{Symbol=>String}]        options  The options hash
    #   @option [Boolean] :noop    (false)  Set to true if you want noop mode
    #   @option [Boolean] :verbose (true)   Whether or not to log verbosely
    #
    # @yield  [result] Yields the result of action for further checking
    #   @yieldparam [Result] result A ValueObject containing action stats
    # @return [void] This method is a helper for remotely executing tasks
    #
    # @example Use this method when action must be sudone
    #     sudo_with_logging( master, ‘reboot -r’, :verbose => false )
    #
    # @example Pass this a block to perform additional checks
    #     sudo_with_logging( master, ‘apt-get update’ ) do |result|
    #       if result.exit_code == 1
    #         fail_test( ‘Apt has failed us again!’ )
    #       end
    #     end
    #
    # @see TestCase#on
    # @api dsl
    #
    def sudo_with_logging hosts, action, options = {}, &block
      return if options[:noop]

      if hosts.is_a?( Array )
        hosts.each {|h| sudo_with_logging h, action, options, &block }
      else
        result = host.execute( action, options.delete(:verbose) )
        yield result if block_given?
      end
    end
```

## Documentation Guide

Most of our documentation is done with the @tag syntax. With a few execptions tags follow this format:

    @tag [TypeOfValueInBrackets] nameOfValue Multi-word description that
      can span multiple lines, as long as lines after the first have
      greater indentation

Note: The `tag` name and the `nameOfValue` in question cannot contain spaces.

All sections should be considered mandatory, but in practice a committer can walk a contributor through the process and help ensure a high quality of documentation.  When contributing keep especially in mind that an
`@example` block will go a long way in helping understand the use case
(which also encourages use by others) and the @api tag helps to understand the scope of a Pull Request.

Please be liberal with whitespace (not trailing whitespace) and vertical alignment as it helps readability while “in code”. Default indentation is two spaces unless there are readability/vertical alignment concerns.

While the `@params`, `@returns`, etc... may seem redundant, they encourage thinking through exactly what you are doing and because of their strict format they allow a level of tooling not available in regular Ruby.

You are encouraged to run the YARD documentation server locally by:

```console
    $ rake docs
```

or

```console
    $ rake docs:bg
```

depending on whether you want the server to run in the foreground or not

Wait for the documentation to compile and then point your browser to [http://localhost:8808](http://localhost:8808).


## A Simple YARD Reference

A Hash that must be in `{:symbol => ‘string’}` format:

    @param [Hash<Symbol, String>] my_hash

This is also valid, and maybe more obvious to those used to Ruby:

    @param [Hash{Symbol=>String}]

When specifying an options hash you use `@option` to specify keys/values:

    @param [Hash{Symbol=>String}] my_opts An options hash
    @option my_opts [ClassOfValue] :key_in_question A Description
    @option my_opts [Fixnum]       :log_level       The log level to run in.
    @option my_opts [Boolean]      :turbo (true)    Who doesn’t want turbos?

This parameter takes an unordered list of Strings, Fixnums, and Floats:

    @param [Array<String, Fixnum, Float>]

This is an ordered list of String, then Fixnum:

    @param [Array<(String, Fixnum)>]

This is a parameter that needs to implement certain methods:

    @param [#[], #to_s]

This documents that a method may return any of the types listed:

    @return [String, self, nil]

This is the return statement for a method only used for side effects:

    @return [void]

If a method returns a boolean (TrueClass or FalseClass) write:

    @return [Boolean]

List possible classes that the method may raise:

    @raise [Beaker::PendingTest]

List parameter names yielded by a method:

    @yield [result, self]

And specify what kind of object is yielded:

    @yieldparam [Result] result

An `example` block contains a tag, description and then indented code:

    @example Accessing Host defaults using hash syntax
        host[‘platform’]  #=> ‘debian-6-amd64’

The `api` tag can have anything behind it, please use the following when documenting harness methods:

    @api dsl        Part of the testing dsl used within tests
    @api public     Methods third party integrations can rely on
    @api private    Methods private to the harness, not to be used externally

When deprecating a method include information on newer alternatives:

    @deprecated This method is horrible. Please use {#foo} or {#bar}.

When you want to reference other information use:

    @see ClassOrModule
    @see #other_method
    @see http://web.url.com/reference Title for the link

