{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://catalog.lintel.tools/schemas/schemastore/ops-yaml/_shared/latest--rev.014.json",
  "title": "ops.yaml",
  "description": "Configuration for `ops` (rev. 014)",
  "x-lintel": {
    "source": "https://raw.githubusercontent.com/LeShaunJ/ops-schema/main/var/src/rev.014.json",
    "sourceSha256": "5a74ca60543daaf92e12dc7bf350b792a98a2c71328ecd536cd3d89e58833bbb"
  },
  "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": "<command>"
        }
      },
      "patternProperties": {
        "^[\\w-]+$": {
          "title": "ActionObject",
          "description": "A command configuration.",
          "type": "object",
          "required": [
            "command"
          ],
          "default": "<command>",
          "propertyNames": {
            "enum": [
              "alias",
              "command",
              "description",
              "load_secrets"
            ]
          },
          "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-]+$"
            },
            "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!"
            },
            "load_secrets": {
              "title": "Load Secrets",
              "$ref": "#/$defs/LoadSecrets",
              "examples": [
                true
              ]
            }
          }
        }
      }
    },
    "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",
          "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",
          "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",
          "type": "array",
          "items": {
            "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.",
            "type": "string",
            "allOf": [
              {
                "$ref": "#/$defs/CommandString"
              }
            ]
          },
          "minItems": 1,
          "examples": [
            [
              "bundle install --quiet"
            ]
          ]
        },
        "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"
            ]
          ]
        },
        "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"
        }
      }
    },
    "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",
          "environment",
          "environment_aliases",
          "exec",
          "gem",
          "secrets",
          "sshkey"
        ]
      },
      "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_file_prefix": "bg_",
            "shell": "/bin/sh"
          },
          "propertyNames": {
            "enum": [
              "log_file_prefix",
              "shell"
            ]
          },
          "properties": {
            "log_file_prefix": {
              "title": "LogFilePrefix",
              "description": "Optional text to prepend to a background action log's filename.",
              "default": "app_",
              "allOf": [
                {
                  "$ref": "#/$defs/FileName"
                }
              ]
            },
            "shell": {
              "title": "Shell",
              "description": "A path to the shell that should be used to perform background actions.",
              "default": "/bin/sh",
              "allOf": [
                {
                  "$ref": "#/$defs/Path"
                }
              ]
            }
          }
        },
        "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"
            }
          }
        },
        "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"
            }
          }
        },
        "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_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": "[DEPRECATED] This feature was removed from versions `0.8.2` and onward until `1.7.0`.",
              "markdownDescription": "### `DEPRECATED`\n_This feature was removed from versions `0.8.2` and onward until `1.7.0`._\n",
              "$ref": "#/$defs/Deprecated"
            },
            "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"
            }
          }
        }
      }
    }
  },
  "markdownDescription": "Configuration for [`ops`](https://github.com/nickthecook/ops).\n\n```yaml\nrevision: ...\ndependencies: ...\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
        }
      }
    }
  },
  "propertyNames": {
    "enum": [
      "actions",
      "dependencies",
      "options",
      "revision"
    ]
  }
}
