{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://catalog.lintel.tools/schemas/schemastore/ops-yaml/_shared/latest--rev.030.json",
  "title": "ops.yaml",
  "description": "Configuration for `ops` (rev. 030)",
  "x-lintel": {
    "source": "https://raw.githubusercontent.com/LeShaunJ/ops-schema/main/var/src/rev.030.json",
    "sourceSha256": "20dbfaf0e76db65893f176bb3d3fc5fdff4e5b701f8861d973ba3fe6ab254a74"
  },
  "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",
                  "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"
                },
                "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",
          "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
        },
        "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",
          "config",
          "envdiff",
          "environment",
          "environment_aliases",
          "exec",
          "gem",
          "pip",
          "secrets",
          "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"
            }
          }
        },
        "config": {
          "title": "ConfigOptions",
          "description": "Affect how configs are interpreted.",
          "type": "object",
          "minProperties": 1,
          "propertyNames": {
            "enum": [
              "path"
            ]
          },
          "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"
            }
          }
        },
        "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"
            }
          }
        },
        "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",
              "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": "A passphrase to generate the SSH key with.",
              "type": "string",
              "default": "b@dP@55w0rd_tryh@rd3r"
            },
            "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": [
              "fail_on_error"
            ]
          },
          "properties": {
            "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"
    ]
  }
}
