Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 17 additions & 8 deletions apps/docs/content/guides/zerops-yaml-advanced.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -113,21 +113,30 @@ zerops:
run: { envVariables: { NODE_ENV: production } }
```

Supports single parent (`extends: base`) or multiple parents (`extends: [base, logging]`) -- later parents override earlier ones:
The child is a deep copy of the resolved parent with its own keys applied on top. The merge is **recursive, key by key**:

- **Nested objects** (`build`, `run`, `deploy`, `healthCheck`, `readinessCheck`, `routing`, ...): only the keys the child specifies are overwritten, everything else is inherited. `run: { start: x }` in the child keeps the parent's `run.envVariables`, `run.ports`, etc.
- **Maps** (`envVariables`): merged. Child keys are added, same-named keys take the child value, remaining parent keys stay. `KEY: null` removes an inherited variable (`KEY: ""` is a regular empty value); `envVariables: null` drops the whole inherited map.
- **Lists** (`buildCommands`, `prepareCommands`, `initCommands`, `deployFiles`, `ports`, `startCommands`, `crontab`, `cache` as a list): **replaced as a whole**, never appended. Repeat the full list in the child. `[]` clears it.
- **Chains** resolve transitively (`prod` extends `staging` extends `base`) in any file order, up to 25 levels deep. A setup cannot extend itself.
- Must reference another `setup` name in the same file.
- **Multiple parents** (`extends: [base, logging]`): resolved exactly as if `logging` extended `base` and the child extended `logging`. Later parents win over earlier ones (including their own ancestry), the child's own keys win over all parents. Same map-merge / list-replace rules apply at every step.

```yaml
zerops:
- setup: base
build: { buildCommands: [npm run build], deployFiles: ./dist }
- setup: logging
run: { envVariables: { LOG_LEVEL: info } }
build: { buildCommands: [npm ci, npm run build], deployFiles: ./dist }
run: { start: npm start, envVariables: { LOG_LEVEL: info, NODE_ENV: development } }
- setup: prod
extends: [base, logging]
run: { envVariables: { NODE_ENV: production } }
extends: base
build: { buildCommands: [npm ci, npm run build -- --mode=production] } # list replaced, deployFiles inherited
run: { envVariables: { NODE_ENV: production, LOG_LEVEL: null } } # merged: NODE_ENV=production, LOG_LEVEL removed; start inherited
- setup: logging
run: { envVariables: { LOG_LEVEL: debug, LOG_FORMAT: json } }
- setup: prod-debug
extends: [prod, logging] # everything from prod, then LOG_LEVEL=debug and LOG_FORMAT=json from logging; NODE_ENV=production inherited via prod
```

Configuration is **merged at the section level** -- child values override parent values within each section (build, run, deploy), but unspecified sections inherit from parent. Must reference another `setup` name in the same file.

## Base Images

Available runtimes and versions are listed in **Service Stacks (live)** -- injected by `zerops_knowledge` and workflow responses. Some key rules:
Expand Down
72 changes: 69 additions & 3 deletions apps/docs/content/zerops-yaml/specification.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -109,9 +109,75 @@ zerops:

When using `extends`:
- The `extends` value must refer to another service's `setup` value in the same file
- The child service inherits all configuration from the base service
- Configuration is merged at the section level (`build`, `run`, `deploy`)
- You can override specific sections by redefining them
- The child service starts as a full copy of the base service, then its own keys are applied on top
- Merging is recursive, key by key. Redefining `run` in the child does not replace the whole `run` section, only the keys you specify inside it. The same applies to nested objects such as `healthCheck` or `readinessCheck`
- Maps such as `envVariables` are merged: the child's keys are added to the base's keys, and a key defined in both takes the child's value. Setting a key to `null` removes the inherited variable (an empty string `""` is a regular value), and `envVariables: null` drops the whole inherited map
- Lists such as `buildCommands`, `initCommands`, `deployFiles`, `ports` or `startCommands` are replaced as a whole, never appended. If you need to change a list, define the full list in the child
- A base service can itself extend another service. Chains are resolved regardless of the order of services in the file. A service cannot extend itself
- `extends` also accepts a list, for example `extends: [base, logging]`. The child is then resolved exactly as if `logging` extended `base` and the child extended `logging`: later services in the list override earlier ones, and the child's own keys override all of them

The following example shows how maps and lists behave differently:

```yaml
zerops:
- setup: base
build:
base: nodejs@22
buildCommands:
- npm ci
- npm run build
deployFiles: ./dist
run:
base: nodejs@22
start: npm start
envVariables:
LOG_LEVEL: info
NODE_ENV: development

- setup: prod
extends: base
build:
buildCommands:
- npm ci
- npm run build -- --mode=production
run:
envVariables:
NODE_ENV: production
LOG_LEVEL: null

- setup: dev
extends: base
run:
envVariables:
DEBUG: "1"
```

The resolved `prod` service is:

```yaml
setup: prod
build:
base: nodejs@22 # inherited
buildCommands: # list replaced as a whole
- npm ci
- npm run build -- --mode=production
deployFiles: ./dist # inherited
run:
base: nodejs@22 # inherited
start: npm start # inherited
envVariables: # map merged key by key, LOG_LEVEL removed by null
NODE_ENV: production
```

And `dev` keeps everything from `base` and adds `DEBUG`:

```yaml
run:
envVariables:
LOG_LEVEL: info
NODE_ENV: development
DEBUG: "1"
```

:::tip
Create a base service with common configuration and extend it for environment-specific services to keep your `zerops.yaml` file DRY (Don't Repeat Yourself).
Expand Down
97 changes: 86 additions & 11 deletions apps/docs/static/llms-full.txt
Original file line number Diff line number Diff line change
Expand Up @@ -17075,21 +17075,30 @@ zerops:
run: { envVariables: { NODE_ENV: production } }
```

Supports single parent (`extends: base`) or multiple parents (`extends: [base, logging]`) -- later parents override earlier ones:
The child is a deep copy of the resolved parent with its own keys applied on top. The merge is **recursive, key by key**:

- **Nested objects** (`build`, `run`, `deploy`, `healthCheck`, `readinessCheck`, `routing`, ...): only the keys the child specifies are overwritten, everything else is inherited. `run: { start: x }` in the child keeps the parent's `run.envVariables`, `run.ports`, etc.
- **Maps** (`envVariables`): merged. Child keys are added, same-named keys take the child value, remaining parent keys stay. `KEY: null` removes an inherited variable (`KEY: ""` is a regular empty value); `envVariables: null` drops the whole inherited map.
- **Lists** (`buildCommands`, `prepareCommands`, `initCommands`, `deployFiles`, `ports`, `startCommands`, `crontab`, `cache` as a list): **replaced as a whole**, never appended. Repeat the full list in the child. `[]` clears it.
- **Chains** resolve transitively (`prod` extends `staging` extends `base`) in any file order, up to 25 levels deep. A setup cannot extend itself.
- Must reference another `setup` name in the same file.
- **Multiple parents** (`extends: [base, logging]`): resolved exactly as if `logging` extended `base` and the child extended `logging`. Later parents win over earlier ones (including their own ancestry), the child's own keys win over all parents. Same map-merge / list-replace rules apply at every step.

```yaml
zerops:
- setup: base
build: { buildCommands: [npm run build], deployFiles: ./dist }
- setup: logging
run: { envVariables: { LOG_LEVEL: info } }
build: { buildCommands: [npm ci, npm run build], deployFiles: ./dist }
run: { start: npm start, envVariables: { LOG_LEVEL: info, NODE_ENV: development } }
- setup: prod
extends: [base, logging]
run: { envVariables: { NODE_ENV: production } }
extends: base
build: { buildCommands: [npm ci, npm run build -- --mode=production] } # list replaced, deployFiles inherited
run: { envVariables: { NODE_ENV: production, LOG_LEVEL: null } } # merged: NODE_ENV=production, LOG_LEVEL removed; start inherited
- setup: logging
run: { envVariables: { LOG_LEVEL: debug, LOG_FORMAT: json } }
- setup: prod-debug
extends: [prod, logging] # everything from prod, then LOG_LEVEL=debug and LOG_FORMAT=json from logging; NODE_ENV=production inherited via prod
```

Configuration is **merged at the section level** -- child values override parent values within each section (build, run, deploy), but unspecified sections inherit from parent. Must reference another `setup` name in the same file.

## Base Images

Available runtimes and versions are listed in **Service Stacks (live)** -- injected by `zerops_knowledge` and workflow responses. Some key rules:
Expand Down Expand Up @@ -44499,9 +44508,75 @@ zerops:

When using `extends`:
- The `extends` value must refer to another service's `setup` value in the same file
- The child service inherits all configuration from the base service
- Configuration is merged at the section level (`build`, `run`, `deploy`)
- You can override specific sections by redefining them
- The child service starts as a full copy of the base service, then its own keys are applied on top
- Merging is recursive, key by key. Redefining `run` in the child does not replace the whole `run` section, only the keys you specify inside it. The same applies to nested objects such as `healthCheck` or `readinessCheck`
- Maps such as `envVariables` are merged: the child's keys are added to the base's keys, and a key defined in both takes the child's value. Setting a key to `null` removes the inherited variable (an empty string `""` is a regular value), and `envVariables: null` drops the whole inherited map
- Lists such as `buildCommands`, `initCommands`, `deployFiles`, `ports` or `startCommands` are replaced as a whole, never appended. If you need to change a list, define the full list in the child
- A base service can itself extend another service. Chains are resolved regardless of the order of services in the file. A service cannot extend itself
- `extends` also accepts a list, for example `extends: [base, logging]`. The child is then resolved exactly as if `logging` extended `base` and the child extended `logging`: later services in the list override earlier ones, and the child's own keys override all of them

The following example shows how maps and lists behave differently:

```yaml
zerops:
- setup: base
build:
base: nodejs@22
buildCommands:
- npm ci
- npm run build
deployFiles: ./dist
run:
base: nodejs@22
start: npm start
envVariables:
LOG_LEVEL: info
NODE_ENV: development

- setup: prod
extends: base
build:
buildCommands:
- npm ci
- npm run build -- --mode=production
run:
envVariables:
NODE_ENV: production
LOG_LEVEL: null

- setup: dev
extends: base
run:
envVariables:
DEBUG: "1"
```

The resolved `prod` service is:

```yaml
setup: prod
build:
base: nodejs@22 # inherited
buildCommands: # list replaced as a whole
- npm ci
- npm run build -- --mode=production
deployFiles: ./dist # inherited
run:
base: nodejs@22 # inherited
start: npm start # inherited
envVariables: # map merged key by key, LOG_LEVEL removed by null
NODE_ENV: production
```

And `dev` keeps everything from `base` and adds `DEBUG`:

```yaml
run:
envVariables:
LOG_LEVEL: info
NODE_ENV: development
DEBUG: "1"
```

:::tip
Create a base service with common configuration and extend it for environment-specific services to keep your `zerops.yaml` file DRY (Don't Repeat Yourself).
Expand Down
97 changes: 86 additions & 11 deletions apps/docs/static/llms-small.txt
Original file line number Diff line number Diff line change
Expand Up @@ -16766,21 +16766,30 @@ zerops:
run: { envVariables: { NODE_ENV: production } }
```

Supports single parent (`extends: base`) or multiple parents (`extends: [base, logging]`) -- later parents override earlier ones:
The child is a deep copy of the resolved parent with its own keys applied on top. The merge is **recursive, key by key**:

- **Nested objects** (`build`, `run`, `deploy`, `healthCheck`, `readinessCheck`, `routing`, ...): only the keys the child specifies are overwritten, everything else is inherited. `run: { start: x }` in the child keeps the parent's `run.envVariables`, `run.ports`, etc.
- **Maps** (`envVariables`): merged. Child keys are added, same-named keys take the child value, remaining parent keys stay. `KEY: null` removes an inherited variable (`KEY: ""` is a regular empty value); `envVariables: null` drops the whole inherited map.
- **Lists** (`buildCommands`, `prepareCommands`, `initCommands`, `deployFiles`, `ports`, `startCommands`, `crontab`, `cache` as a list): **replaced as a whole**, never appended. Repeat the full list in the child. `[]` clears it.
- **Chains** resolve transitively (`prod` extends `staging` extends `base`) in any file order, up to 25 levels deep. A setup cannot extend itself.
- Must reference another `setup` name in the same file.
- **Multiple parents** (`extends: [base, logging]`): resolved exactly as if `logging` extended `base` and the child extended `logging`. Later parents win over earlier ones (including their own ancestry), the child's own keys win over all parents. Same map-merge / list-replace rules apply at every step.

```yaml
zerops:
- setup: base
build: { buildCommands: [npm run build], deployFiles: ./dist }
- setup: logging
run: { envVariables: { LOG_LEVEL: info } }
build: { buildCommands: [npm ci, npm run build], deployFiles: ./dist }
run: { start: npm start, envVariables: { LOG_LEVEL: info, NODE_ENV: development } }
- setup: prod
extends: [base, logging]
run: { envVariables: { NODE_ENV: production } }
extends: base
build: { buildCommands: [npm ci, npm run build -- --mode=production] } # list replaced, deployFiles inherited
run: { envVariables: { NODE_ENV: production, LOG_LEVEL: null } } # merged: NODE_ENV=production, LOG_LEVEL removed; start inherited
- setup: logging
run: { envVariables: { LOG_LEVEL: debug, LOG_FORMAT: json } }
- setup: prod-debug
extends: [prod, logging] # everything from prod, then LOG_LEVEL=debug and LOG_FORMAT=json from logging; NODE_ENV=production inherited via prod
```

Configuration is **merged at the section level** -- child values override parent values within each section (build, run, deploy), but unspecified sections inherit from parent. Must reference another `setup` name in the same file.

## Base Images

Available runtimes and versions are listed in **Service Stacks (live)** -- injected by `zerops_knowledge` and workflow responses. Some key rules:
Expand Down Expand Up @@ -37509,9 +37518,75 @@ zerops:

When using `extends`:
- The `extends` value must refer to another service's `setup` value in the same file
- The child service inherits all configuration from the base service
- Configuration is merged at the section level (`build`, `run`, `deploy`)
- You can override specific sections by redefining them
- The child service starts as a full copy of the base service, then its own keys are applied on top
- Merging is recursive, key by key. Redefining `run` in the child does not replace the whole `run` section, only the keys you specify inside it. The same applies to nested objects such as `healthCheck` or `readinessCheck`
- Maps such as `envVariables` are merged: the child's keys are added to the base's keys, and a key defined in both takes the child's value. Setting a key to `null` removes the inherited variable (an empty string `""` is a regular value), and `envVariables: null` drops the whole inherited map
- Lists such as `buildCommands`, `initCommands`, `deployFiles`, `ports` or `startCommands` are replaced as a whole, never appended. If you need to change a list, define the full list in the child
- A base service can itself extend another service. Chains are resolved regardless of the order of services in the file. A service cannot extend itself
- `extends` also accepts a list, for example `extends: [base, logging]`. The child is then resolved exactly as if `logging` extended `base` and the child extended `logging`: later services in the list override earlier ones, and the child's own keys override all of them

The following example shows how maps and lists behave differently:

```yaml
zerops:
- setup: base
build:
base: nodejs@22
buildCommands:
- npm ci
- npm run build
deployFiles: ./dist
run:
base: nodejs@22
start: npm start
envVariables:
LOG_LEVEL: info
NODE_ENV: development

- setup: prod
extends: base
build:
buildCommands:
- npm ci
- npm run build -- --mode=production
run:
envVariables:
NODE_ENV: production
LOG_LEVEL: null

- setup: dev
extends: base
run:
envVariables:
DEBUG: "1"
```

The resolved `prod` service is:

```yaml
setup: prod
build:
base: nodejs@22 # inherited
buildCommands: # list replaced as a whole
- npm ci
- npm run build -- --mode=production
deployFiles: ./dist # inherited
run:
base: nodejs@22 # inherited
start: npm start # inherited
envVariables: # map merged key by key, LOG_LEVEL removed by null
NODE_ENV: production
```

And `dev` keeps everything from `base` and adds `DEBUG`:

```yaml
run:
envVariables:
LOG_LEVEL: info
NODE_ENV: development
DEBUG: "1"
```

:::tip
Create a base service with common configuration and extend it for environment-specific services to keep your `zerops.yaml` file DRY (Don't Repeat Yourself).
Expand Down
Loading