skippyPeanutButter/yaml_bot

View on GitHub
RULES_DEFINITION.md

Summary

Maintainability
Test Coverage
# YAMLBOT RULES DEFINITION

This document details YamlBot rules specification. Using the details discussed
below, users can craft their own `.yamlbot.yml` rules for validating yaml-based
files according to a specification. Examples of yaml-based tools that can be
validated include [travis-ci](https://travis-ci.org/),
[rubocop](https://github.com/bbatsov/rubocop), and
[jervis](https://github.com/samrocketman/jervis).

The general layout of a `.yamlbot.yml` file is as follows:

```yaml
defaults:
  'default values for rules'
rules:
  - key: 'yaml.address'
    required_key: true|false
    and_requires: ['list of yaml addresses']
    or_requires: ['list of yaml addresses']
    value_whitelist: ['list of values']
    value_blacklist: ['list of values']
    types: ['list of types']
```

### Key definitions

- `defaults` - This section of the rules file is where default values can be
  specified for the keys `required_key`, `and_requires`,
  `or_requires`, `value_whitelist`, `value_blacklist`, and 'types'.
  This key is optional if a user does not wish to specify defaults.

  Note: Specific values defined under individual keys will override
  any default values.

- `rules` - This section is where the rules for yaml file validation are
  specified. This key is required for `YamlBot` to successfully parse
  the rules file.

- `key` - This key is *required*. A rules file must be made up of a
  list of keys that need to be validated. `key` requires a string value,
  which denotes the name of the key being validated. If a user desires
  to validate a nested key, then `.` delimiter must be used to denote
  the parent-child relationship of nested keys.

  Example:
  Sample .yamlbot.yml

  ```yaml
    rules:
      - key: person.age
        required_key: true
        types: [number]
  ```

  Sample yaml file being validated

  ```yaml
    person:
      age: 43
  ```

  Nested keys can be specified up to `nth` level of nesting using the
  `.` delimiter.

- `required_key` - This key is *required* only if it is not defined in
  the `defaults` section. Every key in the list of key being
  validated must be specified as required or not.

- `and_requires` - This key is optional. It determines additional keys that
  *must* be part of the yaml file being validated if a
  particular key is defined.

  Example:
  ```yaml
  rules:
   - key: keya
     required_key: false
     and_requires: [keyb]
  ```
  The above rules specifies that if `keya` is defined in the
  yaml file being validated, then `keyb` must also be defined
  for the yaml file to be successfully validated.

- `or_requires` - This key is optional, if a particular key is a required_key
  and is missing, then a yaml file may still be valid if any of
  the keys in the `or_requires` list exists and is properly
  defined.

  Example:
  ```yaml
  rules:
    - key: keya
      required_key: true
      and_requires: [keyb]
  ```
  The above rules specifies that if `keya` is required in the
  yaml file being validated and is missing, then the yaml file
  will still be marked as valid if `keyb` exists in the yaml
  file with a valid value.

- `value_whitelist` - This key is optional. It defines a list of possible values
  that a key may take on. If this list is defined and a key
  does not have a value specified within this list then that
  key will fail validation.

- `value_blacklist` - This key is optional. It defines a list of values that a
  key may *not* take on. If this list is defined and a key
  has a value defined in this list, then that key will fail
  validation.

- `types` - This key is optional. It defines a list of the possible data types
  that a key's value may be.
  Possible types include 'list', 'object', 'string', 'boolean',
  'number'.

  Example:
  ```yaml
  - key: age
    required_key: true
    types: [number]
  - key: ethnicity
    required_key: false
    types: [string, list]
  ```

  Types are denoted in yaml as follows.

  *List*
  key `groceries` takes an array of items as its value

  ```yaml
    groceries:
      - apples
      - bananas
      - carrots
    or

    groceries: [apples, bananas, carrots]
  ```

  *Object*
  key `car` takes a map/hash of keys with their own values

  ```yaml
    car:
      wheels: 4
      transmission: automatic
      color: blue
  ```

  *String*
  key 'name' takes a string literal as its value

  ```yaml
    name: Louis
  ```

  *Boolean*
  key `can_fly` takes a boolean as its value

  ```yaml
    can_fly: false
  ```

  *Number*
  key `age` takes an integer number as its value
  key `price` takes a floating point number as its value

  ```yaml
    age: 2
    price: 3.99
  ```
### Examples

The examples that follow specify several sample yaml files and their accompanying
`.yamlbot.yml` files used to validate them.

```yaml
defaults:
  required_key: true
rules:
  - key: person
    types: [object]
  - key: person.name
    types: [string]
  - key: person.age
    types: [number]
  - key: person.haircolor
    required_key: false
    types: [string]
  - key: person.race
    types: [string]
    value_whitelist: [dwarf, highelf, human, orc, hobbit]
```

```yaml
person:
  name: Frodo
  age: 20
  race: hobbit
```

The above yaml file would pass validation due to defining all of the required
keys with valid values.

---

```yaml
defaults:
  required_key: false
  types: [string, list]
rules:
  - key: language
    types: [string]
    value_whitelist: [c, go, java, objective-c, python, ruby, swift]
  - key: before_install
  - key: install
  - key: before_script
  - key: script
```

```yaml
language: java
install:
  - export JAVA_HOME='/usr/bin/java1.8/'
  - mvn install
script: mvn test
```

The above yaml file would pass validation due to defining all of the keys with
valid values. Although, an empty yaml file would've passed validation due to
no keys being marked as *required* in the `defaults` section.

---

```yaml
rules:
  - key: bookshelf_items
    required_key: true
    types: [string, list]
  - key: toybox_items
    required_key: false
    types: [string, list]
    value_blacklist: [legos, barbies, hotwheels]
```

```yaml
toybox:
  - 'barbies'
  - 'batman'
  - 'beanie baby'
bookshelf_items:
  - 'Brittanica Encyclopedia'
  - 'How to adult for dummies'
  - 'YAML for beginners'
```

The above yaml file would fail validation due to defining the `toybox_items`
key with a blacked listed value.