# project

project files and directories

A project is a directory with a winch.yaml file and the inventories, pipelines, and recipes that it uses. winch reads the project in the current directory.

## Minimal project

One winch.yaml with a name, a host, and one step:

```
# winch.yaml
name: demo
hosts:
  web1.example.com:
    address: 192.0.2.10
steps:
  - name: Write the message of the day
    file:
      path: /etc/motd
      content: "Managed by winch.\n"
```

Check it, show the changes, then make them:

```
winch validate
winch plan
winch apply

# winch writes /etc/motd on web1.example.com.
```

## Hosts

winch connects with the OpenSSH client and its SSH config. The login user is root, or has passwordless sudo. A host needs nothing else installed: winch sends a helper program to /var/lib/winch/ on the host and runs it there. Run winch doc remote.

## When the project grows

Move the hosts into inventories, the steps into pipelines, and groups of steps into recipes:

```
winch.yaml               the project file
inventories/
  production.yaml        an inventory: hosts and groups
  test.yaml
pipelines/
  site.yaml              a pipeline: stages and steps
recipes/
  nginx/
    recipe.yaml          a recipe: variables, steps, and handlers
    templates/site.tmpl  the templates of the recipe
    files/tls.conf       the files of the recipe
```

The name of an inventory or a pipeline is its file name without .yaml. Plan and apply then name the pipeline: winch plan site.

An inventory, a pipeline, or a recipe can also be a key in winch.yaml, under inventories, pipelines, or recipes. The value of the key is the content of the file. A name in both places is an error.

## Top-level inventory and pipeline

hosts and groups at the top of winch.yaml are the only inventory of the project. They work with any number of pipelines. steps, handlers, parallelism, and health at the top of winch.yaml are the only pipeline. Then plan and apply take no pipeline name.

## YAML

All files are YAML 1.2. Only true and false are booleans: yes, no, on, and off are strings. File modes are strings: mode: "0644". Unknown keys and duplicate keys are errors. Anchors and aliases work. Merge keys (\<\<) do not. winch fmt fixes the indentation and the step key order.

## Keys

| Key | Type | Default | Meaning |
| --- | --- | --- | --- |
| [`name`](#project.name) | string | required | letters, digits, ., \_, and - |
| [`inventory`](#project.inventory) | string | - | default for --inventory |
| [`recipients`](#project.recipients) | list of strings | - | age public keys |
| [`ssh_config`](#project.ssh_config) | string | - | SSH config file for ssh -F |
| [`vars`](#project.vars) | map | - | shared variable defaults |
| [`inventories`](#project.inventories) | map | - | inventories kept in winch.yaml |
| [`pipelines`](#project.pipelines) | map | - | pipelines kept in winch.yaml |
| [`recipes`](#project.recipes) | map | - | recipes kept in winch.yaml |
| [`hosts`](#project.hosts) | map | - | hosts of the only inventory |
| [`groups`](#project.groups) | map | - | groups of the only inventory |
| [`steps`](#project.steps) | list of steps | - | steps of the only pipeline |
| [`handlers`](#project.handlers) | map of lists of steps | - | handlers of the only pipeline |
| [`parallelism`](#project.parallelism) | integer | - | parallelism of the only pipeline |
| [`health`](#project.health) | map | - | health gate of the only pipeline |

### `project.name` {#project.name}

string, required

Letters, digits, ., \_, and -. It does not start with a dot. Hosts keep pending handlers and other state of the project under this name.

### `project.inventory` {#project.inventory}

string

Default for --inventory. A project with more than one inventory and no default makes every run name its inventory with --inventory.

### `project.recipients` {#project.recipients}

list of strings

Age public keys. winch encrypts each secret for all of them. winch secret init adds a key.

### `project.ssh_config` {#project.ssh_config}

string

Path of an SSH config file, relative to the project directory. winch passes it to every ssh with -F, and ssh reads it instead of \~/.ssh/config. The file can have the line Include \~/.ssh/config. Run winch doc remote.

### `project.vars` {#project.vars}

map

Shared variable defaults, by name. A default can be a !secret, an !expr, or a !tpl. Run winch doc variables.

### `project.inventories` {#project.inventories}

map

Inventories kept in winch.yaml, by name. The value of each is the content of an inventory file, as in inventories/\<name\>.yaml.

### `project.pipelines` {#project.pipelines}

map

Pipelines kept in winch.yaml, by name. The value of each is the content of a pipeline file, as in pipelines/\<name\>.yaml.

### `project.recipes` {#project.recipes}

map

Recipes kept in winch.yaml, by name. The value of each is the content of a recipe file, as in recipes/\<name\>/recipe.yaml. Such a recipe has no templates/ or files/ directory. Its steps cannot use template, source, or the key of repo.

### `project.hosts` {#project.hosts}

map

Hosts of the only inventory, as in an inventory file. The project then has no other inventory. It can have any number of pipelines.

### `project.groups` {#project.groups}

map

Groups of the only inventory, as in an inventory file.

### `project.steps` {#project.steps}

list of steps

Steps of the only pipeline. It has one stage on all hosts, and both have the name of the project. The project then has no other pipeline. Plan and apply take no pipeline name.

### `project.handlers` {#project.handlers}

map of lists of steps

Handlers of the only pipeline, as in a pipeline file.

### `project.parallelism` {#project.parallelism}

integer

Parallelism of the only pipeline, as in a pipeline file.

### `project.health` {#project.health}

map

Health gate of the only pipeline, as in a pipeline file.
