{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://catalog.lintel.tools/schemas/schemastore/ops-yaml/_shared/latest--rev.037.json",
  "title": "ops.yaml",
  "description": "Configuration for `ops` (rev. 037)",
  "x-lintel": {
    "source": "https://raw.githubusercontent.com/LeShaunJ/ops-schema/main/var/src/rev.037.json",
    "sourceSha256": "d2abdcf9c57e115574693430344ff79c9d433a763ddad90c7817ab7123c45f0f"
  },
  "type": "object",
  "properties": {
    "actions": {
      "title": "ActionMap",
      "description": "A collection of commands to run via `ops`. If the first argument to `ops` is not a `builtin`, `ops` will look for an action with that name.",
      "markdownDescription": "A collection of commands to run via `ops`. If the first argument to `ops` is not a `builtin`, `ops` will look for an action with that name.\n\n_For more information, see the [Actions](https://github.com/nickthecook/ops/blob/main/docs/actions.md) documentation on [GitHub](https://github.com/nickthecook/ops)._\n",
      "type": "object",
      "minProperties": 1,
      "propertyNames": {
        "title": "<action>",
        "pattern": "^\\b[\\w-]+\\b$"
      },
      "default": {
        "<action>": "<command>"
      },
      "patternProperties": {
        "^[\\w-]+$": {
          "oneOf": [
            {
              "title": "InlineCommand",
              "allOf": [
                {
                  "description": "A simple command, or—though not recommended—a script, to run. Only use this pattern if the command's intent is easy to decipher.",
                  "markdownDescription": "A simple command, or—*though, not recommended*—a script, to run. Only use this pattern if the command's intent is easy to decipher."
                },
                {
                  "$ref": "#/$defs/CommandString"
                }
              ]
            },
            {
              "title": "ActionObject",
              "description": "A command configuration.",
              "type": "object",
              "required": [
                "command"
              ],
              "default": "<command>",
              "propertyNames": {
                "enum": [
                  "alias",
                  "aliases",
                  "command",
                  "description",
                  "in_envs",
                  "load_secrets",
                  "not_in_envs",
                  "param_expansion",
                  "shell_expansion",
                  "skip_before_hooks",
                  "skip_in_envs"
                ]
              },
              "properties": {
                "alias": {
                  "title": "Alias",
                  "description": "A single alias for the action. If the first argument to `ops` is not a builtin or an action name, `ops` will look for an alias that matches the argument.",
                  "markdownDescription": "A single alias for the action. If the first argument to `ops` is not a builtin or an action name, `ops` will look for an alias that matches the argument.",
                  "type": "string",
                  "pattern": "^[\\w-]+$"
                },
                "aliases": {
                  "title": "AliasList",
                  "description": "In addition to the `alias` property, you can specify multiple aliases for an action. Specifying both properties is not recommended.",
                  "markdownDescription": "In addition to the `alias` property, you can specify multiple aliases for an action. Specifying both properties is not recommended.",
                  "type": "array",
                  "items": {
                    "allOf": [
                      {
                        "title": "Alias",
                        "description": "A single alias for the action. If the first argument to `ops` is not a builtin or an action name, `ops` will look for an alias that matches the argument.",
                        "markdownDescription": "A single alias for the action. If the first argument to `ops` is not a builtin or an action name, `ops` will look for an alias that matches the argument.",
                        "type": "string",
                        "pattern": "^[\\w-]+$"
                      }
                    ]
                  }
                },
                "command": {
                  "title": "Command",
                  "description": "A command or script to execute when the action is called.",
                  "type": "string",
                  "default": "true",
                  "allOf": [
                    {
                      "$ref": "#/$defs/CommandString"
                    }
                  ]
                },
                "description": {
                  "title": "Description",
                  "description": "A summary of the command's intent and its usage. When a user runs, `ops help`, the text here will display beside the command's name; otherwise, it will simply display the command script. It is best practice to describe your command.",
                  "markdownDescription": "A summary of the command's intent and its usage. When a user runs, `ops help`, the text here will display beside the command's name; otherwise, it will simply display the command script. It is best practice to describe your command.",
                  "type": "string",
                  "minLength": 1,
                  "default": "DESCRIBE ME!"
                },
                "in_envs": {
                  "title": "Only in Evnironment(s)",
                  "description": "Limit possibly destructive actions to only being used in certain environments. If the action is excuted in an environment missing from this list, it will exit with an error.",
                  "$ref": "#/$defs/EnvList"
                },
                "load_secrets": {
                  "title": "Load Secrets",
                  "$ref": "#/$defs/LoadSecrets",
                  "examples": [
                    true
                  ]
                },
                "not_in_envs": {
                  "title": "Not in Evnironment(s)",
                  "description": "Prevent possibly destructive actions from being used in certain environments. If the action is excuted in an environment within this list, it will exit with an error.",
                  "$ref": "#/$defs/EnvList"
                },
                "param_expansion": {
                  "title": "Enable Parameter Expansion",
                  "description": "Sometimes, a command implementation may call for variable interpetation. This is semi-achieved with `shell_expansion` by default; however, unless the command is a pass-through to a script, there's no way to interpret parameters as postional variables. Enter `param_expansion`. Setting this to `true` instructs `ops` to bind any aguements passed during execution to positional variables within the `command` script.",
                  "markdownDescription": "Sometimes, a command implementation may call for variable interpetation. This is semi-achieved with `shell_expansion` by default; however, unless the command is a pass-through to a script, there's no way to interpret parameters as postional variables. Enter `param_expansion`. Setting this to `true` instructs `ops` to bind any aguements passed during execution to positional variables within the `command` script.",
                  "type": "boolean",
                  "examples": [
                    true
                  ]
                },
                "shell_expansion": {
                  "title": "Disable Shell Expansion",
                  "description": "By default, `ops` executes actions with shell expansion, which means variable references are expanded, file globbing is done, and quotes behave as one would expect. However, this can get in the way sometimes. For actions like this, one can disable shell expansion, losing variable and glob interpolation and other shell features but gaining some predictability.",
                  "markdownDescription": "By default, `ops` executes actions with shell expansion, which means variable references are expanded, file globbing is done, and quotes behave as one would expect. However, this can get in the way sometimes. For actions like this, one can disable shell expansion, losing variable and glob interpolation and other shell features but gaining some predictability.",
                  "type": "boolean",
                  "examples": [
                    false
                  ]
                },
                "skip_before_hooks": {
                  "title": "Skip Before-Hooks",
                  "description": "You may have some actions that don't need to run before hooks. For example, an action that removes container images to allow a developer to force a clean build from the latest source, or free up disk space.\n\nIn this case, you can configure that action to skip the hooks.\n",
                  "type": "boolean",
                  "examples": [
                    true
                  ]
                },
                "skip_in_envs": {
                  "title": "Skip in Evnironment(s)",
                  "description": "Similar to `not_in_envs`, except it will not exit with an error if executed in any of the specified environments.",
                  "$ref": "#/$defs/EnvList"
                }
              }
            }
          ]
        }
      }
    },
    "dependencies": {
      "title": "Dependencies",
      "description": "Dependencies listed in the `dependencies` section of `ops.yml` are satisfied when the `ops up` command is run. Some dependencies will be un-satisfied when you run `ops down`; e.g. services will be stopped, but packages won't be uninstalled.\n\nThis feature allows developers that are new to a project to get up and running without knowing anything about the app itself. Your `ops.yml` should allow a developer to `ops up && ops start` to run an application.\n",
      "markdownDescription": "Dependencies listed in the `dependencies` section of `ops.yml` are satisfied when the `ops up` command is run. Some dependencies will be un-satisfied when you run `ops down`; e.g. services will be stopped, but packages won't be uninstalled.\n\nThis feature allows developers that are new to a project to get up and running without knowing anything about the app itself. Your `ops.yml` should allow a developer to `ops up && ops start` to run an application.\n\n_For more information, see the [Dependencies](https://github.com/nickthecook/ops/blob/main/docs/dependencies.md) documentation on [GitHub](https://github.com/nickthecook/ops)._\n",
      "type": "object",
      "minProperties": 1,
      "propertyNames": {
        "enum": [
          "apk",
          "apt",
          "brew",
          "cask",
          "custom",
          "dir",
          "docker",
          "gem",
          "pip",
          "snap",
          "sshkey"
        ]
      },
      "properties": {
        "apk": {
          "title": "apkPackageList",
          "description": "- Specifies that a particular package from `apk` is needed.\n- Will only run if the `apk` command is in the `$PATH` (usually only on Alpine linux).",
          "markdownDescription": "* Specifies that a particular package from `apk` is needed.\n* Will only run if the `apk` command is in the `$PATH` (usually only on Alpine linux).",
          "$ref": "#/$defs/PackageList"
        },
        "apt": {
          "title": "aptPackageList",
          "description": "- Specifies that a particular package from `apt` is needed.\n- Will only run if the `apt` executable is in the `$PATH`.\n- Can specify a version with, e.g.: `curl/7.52.1-5+deb9u7`.\n- Run `apt-cache policy curl` to get available versions.",
          "markdownDescription": "* Specifies that a particular package from `apt` is needed.\n* Will only run if the `apt` executable is in the `$PATH`.\n* Can specify a version with, e.g.: `curl/7.52.1-5+deb9u7`.\n* Run `apt-cache policy curl` to get available versions.",
          "$ref": "#/$defs/PackageList"
        },
        "brew": {
          "title": "brewPackageList",
          "description": "- Specifies that a particular `brew` package is needed.\n- Will only run if you're on a Mac.",
          "markdownDescription": "* Specifies that a particular `brew` package is needed.\n* Will only run if you're on a Mac.",
          "type": "array",
          "items": {
            "$ref": "#/$defs/PackageBrew"
          },
          "minItems": 1,
          "uniqueItems": true
        },
        "cask": {
          "title": "caskPackageList",
          "description": "- Specifies that a particular `brew cask` package is needed.\n- Will only run if you're on a Mac.",
          "markdownDescription": "* Specifies that a particular `brew cask` package is needed.\n* Will only run if you're on a Mac.",
          "type": "array",
          "items": {
            "$ref": "#/$defs/PackageBrew"
          },
          "minItems": 1,
          "uniqueItems": true
        },
        "custom": {
          "title": "CustomCommandList",
          "description": "- Runs the given command.\n- Can't tell if the command needs to be run or not, so always runs it on `ops up`.\n- Therefore, the command should be idempotent.\n- It's also a good idea to prevent it from printing output unless it encounters an error, to keep the ops output clean.\n- If a `custom` dependency is given as a hash, you can define separate `up` and `down` actions that are run when `ops up` or `ops down` are called, respectively.\n",
          "markdownDescription": "* Runs the given command.\n* Can't tell if the command needs to be run or not, so always runs it on `ops up`.\n* Therefore, the command should be [**idempotent**](https://en.wikipedia.org/wiki/Idempotence).\n* It's also a good idea to prevent it from printing output unless it encounters an error, to keep the ops output clean.\n\n#### `custom` dependencies with `up` and `down`\n\nIf a `custom` dependency is given as a hash, you can define separate `up` and `down` actions that are run when `ops up` or `ops down` are called, respectively.\n\n```yaml\ndependencies:\n\tcustom:\n\t\t- init file:\n\t\t\tup: touch file\n\t\t\tdown: rm file\n```\n\nYou can also define only the `down` command, which will execute on `ops down`; nothing will be executed by the dependency on `ops up`.\n\n> **NOTE:** The lines with `up` and `down` are indented past the beginning of the text `init file`. YAML considers `- ` in a list to be part of the indentation, and `up` and `down` must be _children_ of the name of the custom depdenceny, not siblings. Therefore, the following is **incorrect**:\n>\n> ```yaml\n> dependencies:\n> \tcustom:\n> \t\t- init file:\n> \t\t\tup: touch file\n> \t\t\tdown: rm file\n> ```\n>\n> as it results in a Hash like:\n> \n> ```ruby\n> {\n> \t\"init file\" => nil,\n> \t\"up\" => \"touch file\",\n> \t\"down\" => \"touch file\"\n> }\n> ```\n",
          "type": "array",
          "items": {
            "title": "CustomCommand",
            "description": "A list of coustom command configurations.",
            "oneOf": [
              {
                "$ref": "#/$defs/CommandString"
              },
              {
                "title": "UpDownHash",
                "description": "A key/value pair describing a custom `ops up` and/or `ops down` configuration.",
                "type": "object",
                "propertyNames": {
                  "title": "<up_down_name>"
                },
                "examples": [
                  {
                    "init file": {
                      "up": "touch file",
                      "down": "rm file"
                    }
                  }
                ],
                "minProperties": 1,
                "maxProperties": 1,
                "default": {
                  "up&down": {
                    "up": "<upCommand>",
                    "down": "<downCommand>"
                  }
                },
                "patternProperties": {
                  "^\\b.+\\b$": {
                    "title": "UpDownConfig",
                    "description": "A custom `ops up` and/or `ops down` configuration.",
                    "markdownDescription": "A custom `ops up` and/or `ops down` configuration.",
                    "type": "object",
                    "properties": {
                      "up": {
                        "title": "upCommand",
                        "description": "An idempotent command or script to run as a dependency when `ops up` is executed.",
                        "markdownDescription": "An idempotent command or script to run as a dependency when `ops up` is executed.",
                        "default": "touch file",
                        "type": [
                          "string",
                          "boolean"
                        ],
                        "allOf": [
                          {
                            "$ref": "#/$defs/CustomCommand"
                          }
                        ]
                      },
                      "down": {
                        "title": "downCommand",
                        "description": "An idempotent command or script to run as a dependency when `ops down` is executed.",
                        "markdownDescription": "An idempotent command or script to run as a dependency when `ops down` is executed.",
                        "default": "rm file",
                        "type": [
                          "string",
                          "boolean"
                        ],
                        "allOf": [
                          {
                            "$ref": "#/$defs/CustomCommand"
                          }
                        ]
                      }
                    },
                    "examples": [
                      {
                        "up": "touch file",
                        "down": "rm file"
                      }
                    ],
                    "minProperties": 1,
                    "default": {
                      "up": "<upCommand>",
                      "down": "<downCommand>"
                    },
                    "additionalProperties": false
                  }
                }
              }
            ],
            "examples": [
              "bundle install --quiet",
              {
                "init file": {
                  "up": "touch file",
                  "down": "rm file"
                }
              }
            ]
          },
          "examples": [
            [
              "bundle install --quiet",
              {
                "init file": {
                  "up": "touch file",
                  "down": "rm file"
                }
              }
            ]
          ],
          "minItems": 1,
          "uniqueItems": true
        },
        "dir": {
          "title": "DirectoryList",
          "description": "This dependency will ensure the given directory is created when you run `ops up`. This is handy for directories your app needs, but which contain no checked-in files, since `git` won't save empty directories.",
          "$ref": "#/$defs/PathList"
        },
        "docker": {
          "title": "dockerRepository",
          "description": "- Specifies that this repo includes a directory with the given name (e.g. `deps/mysql`) that includes a `docker-compose.yml` file.\n- `ops` will change to the given directory and use `docker-compose` to start, stop, and check the status of this service as needed.\n",
          "markdownDescription": "* Specifies that this repo includes a directory with the given name (e.g. `deps/mysql`) that includes a `docker-compose.yml` file.\n* `ops` will change to the given directory and use `docker-compose` to start, stop, and check the status of this service as needed.\n",
          "$ref": "#/$defs/PathList"
        },
        "gem": {
          "title": "gemPackageList",
          "description": "- Installs the gem with the given name.\n- By default, runs `gem install ...`, but can be configured to use `sudo gem install` or `gem install --user-install` (see below).\n",
          "markdownDescription": "* Installs the gem with the given name.\n* By default, runs `gem install ...`, but can be configured to use `sudo gem install` or `gem install --user-install` (_see below_).\n",
          "$ref": "#/$defs/PackageList",
          "examples": [
            [
              "ejson"
            ]
          ]
        },
        "pip": {
          "title": "pipPackageList",
          "description": "This dependency ensures that the given Python package is installed.",
          "type": "array",
          "items": {
            "$ref": "#/$defs/PackagePip"
          },
          "minItems": 1,
          "uniqueItems": true
        },
        "snap": {
          "title": "snapPackageList",
          "description": "- Specifies that a particular package from `snap` is needed.\n- Unlike `apt`, `brew`, or `apk`, `snap` may be present on any Linux system, and its presence alone probably shouldn't be taken as a sign that ops should install every `snap` listed in dependencies.\n- Therefore, ops will never install `snaps` unless `options.snap.install` is true.",
          "markdownDescription": "- Specifies that a particular package from `snap` is needed.\n- Unlike `apt`, `brew`, or `apk`, `snap` may be present on any Linux system, and its presence alone probably shouldn't be taken as a sign that ops should install every `snap` listed in dependencies.\n- Therefore, ops will never install `snaps` unless `options.snap.install` is true.",
          "$ref": "#/$defs/PackageList"
        },
        "sshkey": {
          "title": "sshKeyList",
          "description": "This dependency will create an SSH key pair with key size 4096 and key algorithm `rsa` at `keys/$environment/user@host` and `keys/$environment/user@host.pub`. It will also add it to your SSH agent, if `SSH_AUTH_SOCK` is set, with a lifetime of 3600 seconds (one hour).\n\nThe key comment, which is visible in the output of `ssh-add -l`, will be set to the name of the directory that contains `ops.yml`. For example, if the directory is named `heliograf`, you would see the following output:\n",
          "markdownDescription": "This dependency will create an SSH key pair with key size 4096 and key algorithm `rsa` at `keys/$environment/user@host` and `keys/$environment/user@host.pub`. It will also add it to your SSH agent, if `SSH_AUTH_SOCK` is set, with a lifetime of 3600 seconds (one hour).\n\nThe key comment, which is visible in the output of `ssh-add -l`, will be set to the name of the directory that contains `ops.yml`. For example, if the directory is named `heliograf`, you would see the following output:\n\n```shell\n$ ssh-add -l\n2048 SHA256:7n9WwisFkDtemOx8O/+D33myKpjOvrjx3PZcNb9y6/Y heliograf (RSA)\n2048 SHA256:Z6oEPBIoBrHv/acYiBGBRYLe2sEONV17tDor3h5eNtc certitude (RSA)\n```\n\nThis output shows that one key from a project called `heliograf` and one key from a project called `certitude` have been loaded.\n",
          "$ref": "#/$defs/PathList",
          "examples": [
            [
              "keys/$environment/user@host"
            ]
          ]
        },
        "terraform": {
          "title": "terraformHandler",
          "type": "array",
          "description": "[DEPRECATED] This feature has been removed as of version `0.2.6`.",
          "markdownDescription": "### `DEPRECATED`\n_This feature has been removed as of version `0.2.6`._\n",
          "$ref": "#/$defs/Deprecated"
        }
      }
    },
    "forwards": {
      "title": "ForwardMap",
      "description": "Sometimes a project is complex enough to split up into multiple directories. In this case, you may have `ops.yml` files in several places, but still want to provide easy access to these actions from the top-level directory.\n\nWith this config, `ops app test` will have the same effect as running `ops test` from the `app` directory. `ops inf deploy` will be the same as `cd infrastructure && ops deploy`.\n\nWhen a command is forwarded to another directory, no config, secrets, or environment variables are set based on the current directory's `ops.yml`, and no hooks are run from the current directory's `ops.yml`.\n\nIf you want access to the top-level directory's config or secrets from the subdirectory, link it in the subdirectory's `ops.yml`.\n",
      "markdownDescription": "Sometimes a project is complex enough to split up into multiple directories. In this case, you may have `ops.yml` files in several places, but still want to provide easy access to these actions from the top-level directory.\n\nWith this config, `ops app test` will have the same effect as running `ops test` from the `app` directory. `ops inf deploy` will be the same as `cd infrastructure && ops deploy`.\n\nWhen a command is forwarded to another directory, no config, secrets, or environment variables are set based on the current directory's `ops.yml`, and no hooks are run from the current directory's `ops.yml`.\n\nIf you want access to the top-level directory's config or secrets from the subdirectory, link it in the subdirectory's `ops.yml`:\n\n```yaml\ndependencies:\n  custom:\n    - ln -sf ../config config\n```\n\n_For more information, see the [Forwards](https://github.com/nickthecook/ops/blob/main/docs/why.md#vforwards) documentation on [GitHub](https://github.com/nickthecook/ops)._\n",
      "type": "object",
      "minProperties": 1,
      "patternProperties": {
        "^[\\w-]+$": {
          "title": "ForwardPath",
          "description": "The path of the forwarded `ops.yml` file.",
          "type": "string",
          "format": "uri-reference",
          "default": "./"
        }
      }
    },
    "hooks": {
      "title": "Hooks",
      "description": "Sometimes you want to run a command before other commands. Some examples:\n\n- You have a number of ops commands that let a developer run different test suites inside a container, and you want to make sure the container image is built beforehand.\n- You have some configuration that needs to happen when the software execution environment changes (e.g. going from dev to staging).\n\nIn this case, you can use the \"hooks feature.\n",
      "markdownDescription": "Sometimes you want to run a command before other commands. Some examples:\n\n* You have a number of ops commands that let a developer run different test suites inside a container, and you want to make sure the container image is built beforehand.\n* You have some configuration that needs to happen when the software execution environment changes (_e.g. going from `dev` to `staging`_).\n\nIn this case, you can use the `hooks` feature.\n\n_For more information, see the [Hooks](https://github.com/nickthecook/ops/blob/main/docs/hooks.md) documentation on [GitHub](https://github.com/nickthecook/ops)._\n",
      "type": "object",
      "minProperties": 1,
      "propertyNames": {
        "enum": [
          "before"
        ]
      },
      "properties": {
        "before": {
          "title": "BeforeHooks",
          "description": "A series of hooks that run before actions. They do not run before builtins like `up` or `exec`.\n\n`before` hooks are always executed before secrets are loaded. If you would like a before hook to have access to secrets, create an action with `load_secrets: true` and call the action from a before hook.\n",
          "markdownDescription": "A series of hooks that run before actions. They do not run before builtins like `up` or `exec`.\n\n`before` hooks are always executed before secrets are loaded. If you would like a before hook to have access to secrets, create an action with `load_secrets: true` and call the action from a before hook.\n",
          "type": "array",
          "items": {
            "description": "A valid command to run before action execution.",
            "$ref": "#/$defs/CommandString"
          },
          "minItems": 1
        }
      }
    },
    "min_version": {
      "allOf": [
        {
          "title": "Minimum Version",
          "description": "A valid semantic version. If an older version of `ops` (v0.12.0 or later) encounters this file, it will print a message and exit.\n\nThe versions you can set for `min_version` will depend on the `revision` of `ops.yaml` you've specified—if specified at all.\n",
          "markdownDescription": "A valid [semantic version](https://semver.org). If an older version of `ops` (_`v0.12.0` or later_) encounters this file, it will print a message like this and exit:\n\n> ```\n> ops.yml specifies minimum version of 0.12.2, but ops version is 0.12.0\n> ```\n\nThe versions you can set for `min_version` will depend on the `revision` of `ops.yaml` you've specified—if specified at all.\n\n_For more information, see the [Version Checking](https://github.com/nickthecook/ops/blob/main/docs/why.md#version-checking) documentation on [GitHub](https://github.com/nickthecook/ops)._\n"
        },
        {
          "$ref": "#/$defs/SemVer"
        }
      ]
    },
    "options": {
      "title": "Options",
      "description": "Options allow the user to change some aspects of `ops` behaviour.",
      "markdownDescription": "Options allow the user to change some aspects of `ops` behaviour.\n\n_For more information, see the [Options](https://github.com/nickthecook/ops/blob/main/docs/options.md) documentation on [GitHub](https://github.com/nickthecook/ops)._\n",
      "type": "object",
      "minProperties": 1,
      "propertyNames": {
        "enum": [
          "apt",
          "background",
          "completion",
          "config",
          "envdiff",
          "environment",
          "environment_aliases",
          "exec",
          "gem",
          "pip",
          "secrets",
          "snap",
          "sshkey",
          "up"
        ]
      },
      "properties": {
        "apt": {
          "title": "AptOptions",
          "description": "Affect the behaviour of `apt` dependencies.",
          "markdownDescription": "Affect the behaviour of `apt` dependencies.",
          "type": "object",
          "minProperties": 1,
          "default": {
            "use_sudo": false
          },
          "propertyNames": {
            "enum": [
              "use_sudo"
            ]
          },
          "properties": {
            "use_sudo": {
              "$ref": "#/$defs/UseSudo/properties/use_sudo"
            }
          }
        },
        "background": {
          "description": "Affect the behaviour of the `background` builtin.",
          "markdownDescription": "Affect the behaviour of the `background` builtin.",
          "type": "object",
          "minProperties": 1,
          "default": {
            "log_filename": "app.log",
            "shell": "/bin/sh"
          },
          "propertyNames": {
            "enum": [
              "log_filename"
            ]
          },
          "properties": {
            "log_filename": {
              "title": "LogFilePrefix",
              "description": "Override the default name for the background action log file.",
              "$ref": "#/$defs/FileName"
            },
            "log_file_prefix": {
              "title": "LogFilePrefix",
              "description": "[DEPRECATED] This feature was removed as version `0.9.4`.",
              "markdownDescription": "### `DEPRECATED`\n_This feature was removed as version `0.9.4`._\n",
              "$ref": "#/$defs/Deprecated"
            },
            "shell": {
              "title": "Shell",
              "description": "[DEPRECATED] This feature was removed as version `0.9.4`.",
              "markdownDescription": "### `DEPRECATED`\n_This feature was removed as version `0.9.4`._\n",
              "$ref": "#/$defs/Deprecated"
            }
          }
        },
        "completion": {
          "allOf": [
            {
              "title": "CompletionOptions",
              "description": "Affect the behaviour of the auto-complete feature.",
              "markdownDescription": "Affect the behaviour of the auto-complete feature.",
              "type": "object",
              "minProperties": 1,
              "default": {
                "include_aliases": true
              }
            },
            {
              "$ref": "#/$defs/Deprecated"
            }
          ]
        },
        "config": {
          "title": "ConfigOptions",
          "description": "Affect how configs are interpreted.",
          "type": "object",
          "minProperties": 1,
          "propertyNames": {
            "enum": [
              "path",
              "preserve_existing_env_vars"
            ]
          },
          "properties": {
            "path": {
              "title": "SecretsPath",
              "description": "Override the config file location (defaults to `./config/<environment>/config.json`).",
              "markdownDescription": "Override the config file location (_defaults to `./config/<environment>/config.json`_).",
              "$ref": "#/$defs/Path",
              "default": "config/${environment}/config.json"
            },
            "preserve_existing_env_vars": {
              "title": "PreserveExistingEnvVars",
              "description": "If `true`, will cause `ops` to only set environment variables from config and secrets if the variable is not already set.",
              "markdownDescription": "If `true`, will cause `ops` to only set environment variables from config _and_ secrets if the variable is not already set.",
              "type": "boolean",
              "default": true
            }
          }
        },
        "envdiff": {
          "title": "EnvDiffOptions",
          "description": "Affect the behaviour of `ops envdiff`.",
          "type": "object",
          "minProperties": 1,
          "default": {
            "ignored_keys": [
              "backend_config_params"
            ]
          },
          "patternProperties": {
            "^\\w+$": {
              "title": "IgnoredKeys",
              "description": "If there's a key you know should be in some environments and not in others, put it in the `envdiff.ignored_keys` option and `ops envdiff` won't mention it again.",
              "markdownDescription": "If there's a key you know should be in some environments and not in others, put it in the `envdiff.ignored_keys` option and `ops envdiff` won't mention it again.",
              "type": "array",
              "items": {
                "description": "Any key within your `config.json/#/environment` and/or `secrets.ejson/#/environment`.",
                "$ref": "#/$defs/NameString",
                "minItems": 1,
                "uniqueItems": true,
                "default": "backend_config_params"
              }
            }
          }
        },
        "environment": {
          "title": "EnvironmentMap",
          "description": "Statically or dynamically set global environment variables, with each key serving as a variable's name.\n\nThe values of these variables are not interpreted by the shell before being set, so variable references like `$environment` will appear literally in the value of the variable.\n",
          "markdownDescription": "Statically or dynamically set global environment variables, with each key serving as a variable's name.\n\n> **NOTE:** _The values of these variables are not interpreted by the shell before being set, so variable references like `$environment` will appear literally in the value of the variable._\n",
          "type": "object",
          "minProperties": 1,
          "default": {
            "PATH": "./bin:${PATH}"
          },
          "patternProperties": {
            "^\\w+$": {
              "title": "EnvVarValue",
              "description": "Either a static value, or a command enclosed between `\"\\\\`...\\\\`\"`.",
              "markdownDescription": "Either a static value, or a command enclosed between `` \"`...`\" ``.",
              "type": "string"
            }
          }
        },
        "environment_aliases": {
          "title": "EnvironmentAliasList",
          "description": "Different software systems use different environment variables to determine the software execution environment. E.g. Ruby on Rails uses `RAILS_ENV`. Thus, `ops` allows the user to specify which variables should also be set to the name of the software environment.\n\nIf any `environment_aliases` are specified in `ops.yml`, `ops` will not change the value of `$environment` unless it is listed as well.\n\n(`ops` will always use `$environment` to detect the software execution environment; `environment_aliases` just makes `ops` set other variables to match it.)\n",
          "markdownDescription": "Different software systems use different environment variables to determine the software execution environment. E.g. Ruby on Rails uses `RAILS_ENV`. Thus, `ops` allows the user to specify which variables should also be set to the name of the software environment.\n\nIf any `environment_aliases` are specified in `ops.yml`, `ops` will not change the value of `$environment` unless it is listed as well.\n\n> NOTE: _`ops` will always use `$environment` to detect the software execution environment; `environment_aliases` just makes `ops` set other variables to match it._\n",
          "type": "array",
          "minItems": 1,
          "uniqueItems": true,
          "examples": [
            [
              "RAILS_ENV",
              "RACK_ENV"
            ]
          ],
          "items": {
            "description": "The name of an environment variable.",
            "$ref": "#/$defs/NameString"
          }
        },
        "exec": {
          "title": "ExecOptions",
          "description": "Affect the behaviour of `ops exec`.",
          "type": "object",
          "minProperties": 1,
          "propertyNames": {
            "enum": [
              "load_secrets"
            ]
          },
          "properties": {
            "load_secrets": {
              "$ref": "#/$defs/LoadSecrets"
            }
          }
        },
        "gem": {
          "title": "GemOptions",
          "description": "Affect the behaviour of `gem` dependencies.",
          "markdownDescription": "Affect the behaviour of `gem` dependencies.",
          "type": "object",
          "minProperties": 1,
          "default": {
            "user_install": true,
            "use_sudo": false
          },
          "propertyNames": {
            "enum": [
              "use_sudo",
              "user_install"
            ]
          },
          "properties": {
            "user_install": {
              "title": "UserInstall",
              "description": "If `true`, causes `ops up` to run `gem install --user-install ejson`.",
              "type": "boolean",
              "default": false
            },
            "use_sudo": {
              "$ref": "#/$defs/UseSudo/properties/use_sudo"
            }
          }
        },
        "pip": {
          "title": "PipOptions",
          "description": "Affect the behaviour of `pip` dependencies.",
          "markdownDescription": "Affect the behaviour of `pip` dependencies.",
          "type": "object",
          "default": {
            "command": "pip3"
          },
          "propertyNames": {
            "enum": [
              "command"
            ]
          },
          "properties": {
            "command": {
              "title": "PipCommand",
              "description": "The path to a `pip` binary, along any options you'd like to run when installing packages.",
              "type": "string",
              "minLength": 1,
              "default": "pip3"
            }
          }
        },
        "secrets": {
          "title": "SecretOptions",
          "description": "Affect how secrets are interpreted.",
          "type": "object",
          "minProperties": 1,
          "propertyNames": {
            "enum": [
              "path"
            ]
          },
          "properties": {
            "path": {
              "title": "SecretsPath",
              "description": "Override the secrets file location (defaults to `./config/<environment>/secrets.json`).",
              "markdownDescription": "Override the secrets file location (_defaults to `./config/<environment>/secrets.json`_).",
              "$ref": "#/$defs/Path",
              "default": "config/${environment}/secrets.ejson"
            }
          }
        },
        "snap": {
          "title": "SnapOptions",
          "description": "Affect the behaviour of `snap` dependencies.",
          "markdownDescription": "Affect the behaviour of `snap` dependencies.",
          "type": "object",
          "minProperties": 1,
          "default": {
            "install": true,
            "use_sudo": false
          },
          "propertyNames": {
            "enum": [
              "install",
              "use_sudo"
            ]
          },
          "properties": {
            "install": {
              "description": "Unlike `apt`, `brew`, or `apk`, `snap` may be present on any Linux system, and its presence alone probably shouldn't be taken as a sign that `ops` should install every snap listed in `dependencies`. Therefore, `ops` will never install snaps unless the `snap.install` option is `true`.\n\nFor example, on Solus Linux, `snap` is necessary to install the `mosquitto` MQTT broker, but on Debian I would `apt install mosquitto-tools` instead. So both of these dependencies would be listed in the `ops.yml`. However, I may still have `snap` present; I just wouldn't want `ops` to install snaps unless I told it to, or it would install both the apt package and the snap.\n\nManaging these options via hard-coded strings in `ops.yml` isn't the best solution, however; this file is checked in, but whether or not to install snaps should be based on environment. In the future, `ops` will support using env vars to set any option, based on a scheme like `apt.use_sudo` == `$APT__USE_SUDO`.\n",
              "markdownDescription": "Unlike `apt`, `brew`, or `apk`, `snap` may be present on any Linux system, and its presence alone probably shouldn't be taken as a sign that `ops` should install every snap listed in `dependencies`. Therefore, `ops` will never install snaps unless the `snap.install` option is `true`.\n\nFor example, on Solus Linux, `snap` is necessary to install the `mosquitto` MQTT broker, but on Debian I would `apt install mosquitto-tools` instead. So both of these dependencies would be listed in the `ops.yml`. However, I may still have `snap` present; I just wouldn't want `ops` to install snaps unless I told it to, or it would install both the apt package and the snap.\n\nManaging these options via hard-coded strings in `ops.yml` isn't the best solution, however; this file is checked in, but whether or not to install snaps should be based on environment. In the future, `ops` will support using env vars to set any option, based on a scheme like `apt.use_sudo` == `$APT__USE_SUDO`.\n",
              "type": "boolean",
              "default": false
            },
            "use_sudo": {
              "$ref": "#/$defs/UseSudo/properties/use_sudo"
            }
          }
        },
        "sshkey": {
          "title": "SshKeyOptions",
          "description": "Affect how SSH keys are generated.",
          "type": "object",
          "minProperties": 1,
          "default": {
            "passphrase": "p@ssw0rd",
            "key_size": 4096
          },
          "propertyNames": {
            "enum": [
              "add_keys",
              "key_algo",
              "key_file_comment",
              "key_lifetime",
              "key_size",
              "passphrase_var"
            ]
          },
          "properties": {
            "add_keys": {
              "title": "AddKeys",
              "description": "If `false`, disables adding the SSH key to `ssh-agent`.",
              "markdownDescription": "If `false`, disables adding the SSH key to `ssh-agent`.",
              "type": "boolean",
              "default": false
            },
            "key_algo": {
              "title": "KeyAlgorithm",
              "description": "The algorithm to generate the SSH key with.",
              "type": "string",
              "enum": [
                "dsa",
                "ecdsa",
                "ecdsa-sk",
                "ed25519",
                "ed25519-sk",
                "rsa"
              ],
              "default": "rsa",
              "examples": [
                "ed25519"
              ]
            },
            "key_file_comment": {
              "title": "KeyFileComment",
              "description": "An optional comment for the SSH key.",
              "type": "string",
              "minLength": 0,
              "default": "My SSH key comment"
            },
            "key_lifetime": {
              "title": "KeyLifetime",
              "description": "The duration, in seconds, at which the SSH key will be removed from `ssh-agent`.",
              "type": "integer",
              "minimum": 0,
              "default": 3600
            },
            "key_size": {
              "title": "KeyAlgorithm",
              "description": "The size at which the SSH key will be generated.\n\n_With the \"ed25519\" algorithm, `key_size` can still be specified, but will be ignored by `ssh-keygen`, since all keys for that algorithm are 256 bits._\n",
              "markdownDescription": "The size at which the SSH key will be generated.\n\n> **NOTE:** _With the `ed25519` algorithm, `key_size` can still be specified, but will be ignored by `ssh-keygen`, since all keys for that algorithm are 256 bits._\n",
              "type": "integer",
              "enum": [
                512,
                1024,
                2048,
                4096
              ],
              "minimum": 512,
              "maximum": 4096,
              "default": 4096
            },
            "passphrase": {
              "title": "KeyPassphrase",
              "description": "[DEPRECATED] This feature was removed as of version `2.0.0`. Please use `options.sshkey.passphrase_var` instead.",
              "markdownDescription": "### `DEPRECATED`\n_This feature was removed as of version `2.0.0`. Please use `options.sshkey.passphrase_var` instead._\n",
              "$ref": "#/$defs/Deprecated"
            },
            "passphrase_var": {
              "title": "PassphraseVar",
              "description": "The name of an environment variable containing the passphrase to generate the SSH key with.",
              "type": "string",
              "pattern": "^\\w*$",
              "default": "SSH_KEY_PASSPHRASE"
            }
          }
        },
        "up": {
          "title": "UpOptions",
          "description": "Affect the behaviour of the `up` builtin.",
          "markdownDescription": "Affect the behaviour of the `up` builtin.",
          "type": "object",
          "minProperties": 1,
          "default": {
            "exit_on_error": true,
            "fail_on_error": true
          },
          "propertyNames": {
            "enum": [
              "exit_on_error",
              "fail_on_error"
            ]
          },
          "properties": {
            "exit_on_error": {
              "title": "Exit-on-Error",
              "description": "By default, `ops up` will simply continue with the next dependency even if the current dependency failed. Set this to `true` if you want `ops up` to exit on the first error it encounters.",
              "markdownDescription": "By default, `ops up` will simply continue with the next dependency even if the current dependency failed. Set this to `true` if you want `ops up` to exit on the first error it encounters.",
              "type": "boolean",
              "default": true
            },
            "fail_on_error": {
              "title": "Fail-on-Error",
              "description": "By default, `ops up` will exit 0 even if any dependencies failed due to errors. Set this to `true` if you want `ops up` to exit non-0 when any of the dependencies fail.",
              "markdownDescription": "By default, `ops up` will exit `0` even if any dependencies failed due to errors. Set this to `true` if you want `ops up` to exit _non-`0`_ when any of the dependencies fail.",
              "type": "boolean",
              "default": true
            }
          }
        }
      }
    }
  },
  "markdownDescription": "Configuration for [`ops`](https://github.com/nickthecook/ops).\n\n```yaml\nrevision: ...\nmin_version: ...\nforwards: ...\ndependencies: ...\nhooks: ...\nactions: ...\noptions: ...\n```\n",
  "$defs": {
    "CommandString": {
      "oneOf": [
        {
          "title": "NoopPass",
          "description": "Executes a `no-op`, exiting successfully with `0`.",
          "markdownDescription": "Executes a `no-op`, exiting successfully with `0`.",
          "type": "string",
          "const": "true",
          "default": "true"
        },
        {
          "title": "NoopFail",
          "description": "Executes a `no-op`, exiting with error code `1`.",
          "markdownDescription": "Executes a `no-op`, exiting with error code `1`.",
          "type": "string",
          "const": "false",
          "default": "false"
        },
        {
          "allOf": [
            {
              "title": "CommandString",
              "default": "echo \"hello, world\"",
              "examples": [
                "terraform init",
                "docker-compose up"
              ],
              "not": {
                "enum": [
                  "true",
                  "false"
                ]
              }
            },
            {
              "$ref": "#/$defs/NonEmptyString"
            }
          ]
        }
      ]
    },
    "Deprecated": {
      "title": "Deprecated",
      "examples": [],
      "readOnly": true
    },
    "EnvList": {
      "title": "EnvironmentList",
      "type": "array",
      "items": {
        "title": "Environment",
        "description": "A list of environment names.",
        "$ref": "#/$defs/NameString"
      },
      "minItems": 1,
      "uniqueItems": true
    },
    "FileName": {
      "title": "FileName",
      "type": "string",
      "pattern": "^(?!.{256,})(?!(aux|clock\\$|con|nul|prn|com[1-9]|lpt[1-9])(?:$|\\.))[^ ][ \\.\\w\\-$()+=\\[\\];#@~,&']+[^\\. ]$",
      "minLength": 1,
      "default": "myfile.txt"
    },
    "LoadSecrets": {
      "description": "If `true`, items in `secrets.ejson` will be loaded before execution, allowing said items to be referenced in the configuration.",
      "type": "boolean",
      "default": false
    },
    "NameString": {
      "title": "NameString",
      "type": "string",
      "pattern": "^[\\w-]+$"
    },
    "NonEmptyString": {
      "title": "NonEmptyString",
      "type": "string",
      "minLength": 1
    },
    "PackageList": {
      "title": "PackageList",
      "type": "array",
      "items": {
        "$ref": "#/$defs/PackageVersioned"
      },
      "minItems": 1,
      "uniqueItems": true
    },
    "PackageBrew": {
      "title": "BrewPackage",
      "description": "The name of a `brew` package. If you need to specify a version, include it after the name, delimited by an `@` symbol.",
      "markdownDescription": "The name of a `brew` package. If you need to specify a version, include it after the name, delimited by an `@` symbol.",
      "type": "string",
      "pattern": "^\\b[\\w:.+-]+\\b(@\\b[0-9.]+\\b[\\w.+-]*\\b)?$",
      "examples": [
        "ruby",
        "openssl@"
      ]
    },
    "PackagePip": {
      "title": "PipPackage",
      "description": "The name of a `pip` package. If you need to specify a version, include it after the name, delimited by `==`.",
      "markdownDescription": "The name of a `pip` package. If you need to specify a version, include it after the name, delimited by `==`.",
      "type": "string",
      "pattern": "^\\b[\\w:.+-]+\\b(==\\b[0-9.]+\\b[\\w.+-]*\\b)?$",
      "examples": [
        "semver",
        "ruamel.yaml==0.17.26"
      ]
    },
    "PackageVersioned": {
      "title": "Package",
      "description": "The name of a package. If you need to specify a version, include it after the name, delimited by a space.",
      "markdownDescription": "The name of a package. If you need to specify a version, include it after the name, delimited by a space.",
      "type": "string",
      "pattern": "^\\b[\\w@:.+-]+\\b( \\b[0-9.]+\\b[\\w.+-]*\\b)?$",
      "examples": [
        "ruby",
        "openssl 0.8.0"
      ]
    },
    "Path": {
      "title": "Path",
      "type": "string",
      "format": "uri-reference"
    },
    "PathList": {
      "title": "PathList",
      "type": "array",
      "items": {
        "allOf": [
          {
            "description": "A valid filepath."
          },
          {
            "$ref": "#/$defs/Path"
          }
        ]
      },
      "minItems": 1,
      "uniqueItems": true
    },
    "SemVer": {
      "title": "SemanticVersion",
      "type": "string",
      "pattern": "^(0|[1-9]\\d*)(?:\\.(0|[1-9]\\d*)(?:\\.(0|[1-9]\\d*)(?:[.-]([0-9A-z-]+(?:\\.[0-9A-z-]+)*)|)(\\+[0-9A-z-]+|)|)|)$"
    },
    "UseSudo": {
      "properties": {
        "use_sudo": {
          "title": "UseSudo",
          "description": "If `false`, causes `ops up` to install the dependency's packages without `sudo`.",
          "type": "boolean",
          "default": true
        }
      }
    },
    "CustomCommand": {
      "title": "CustomCommand",
      "type": "string",
      "allOf": [
        {
          "type": "string",
          "$ref": "#/$defs/CommandString"
        }
      ]
    }
  },
  "propertyNames": {
    "enum": [
      "actions",
      "dependencies",
      "forwards",
      "hooks",
      "min_version",
      "options",
      "revision"
    ]
  }
}
