Syntax reference
This page is the canonical reference for mecapy.yml v1. Each section
maps one-to-one to a Pydantic model in
mecapy_api.services.manifest_v1_models, which is the source of truth.
version: "1"Frozen at "1". Any other value is rejected. A future v2 format will
keep the same key and bump the literal — your existing manifests
stay valid as long as MecaPy keeps the v1 parser around.
package: name: bolt-sizing # required version: 0.1.0 # required, semver description: | # optional One-line summary; multi-line allowed. author: Jane Doe # optional license: MIT # optional visibility: private # optional, default "private" tags: [bolts, mechanics] # optional resources: # optional, see below tier: nano| Field | Type | Default | Notes |
|---|---|---|---|
name | string | — | Package identifier. Kebab-case recommended. |
version | string | — | Strict semver: MAJOR.MINOR.PATCH (optional pre-release tag). |
description | string | null | Free text. |
author | string | null | Free text. |
license | string | null | SPDX identifier (MIT, Apache-2.0, …). |
visibility | enum | "private" | private / internal / public. See visibility. |
tags | list[string] | null | For search/categorisation in the package list. |
resources | object | null | Default resources every function inherits — see below. |
The block is a discriminated union on kind. Each kind has its
own required fields:
runtime: kind: python # mode A — managed version: "3.12" # required, "3.10" | "3.11" | "3.12" requirements: false # optional, install repo-root requirements.txt at buildruntime: kind: dockerfile # mode B — build custom dockerfile: Dockerfile # required, path relative to repo root context: . # optional, default "."runtime: kind: image # mode C — pre-built image: ghcr.io/me/x:1.4 # required, full registry reference with tagPer-kind details and trade-offs: runtime modes.
functions
Section intitulée « functions »A non-empty dict. Each entry has the same shape but two mutually exclusive top fields depending on the runtime mode:
functions: my_function: # ── Mode A only ── handler: pkg.module:function # required in mode A
# ── Modes B/C only ── entrypoint: ["python", "/run.py", "x"] # required in modes B/C, list[str], non-empty
# ── Common ── description: | Free-text description. inputs: diameter: { type: Length, required: true, description: "..." } load: { type: Force } outputs: stress: { type: Stress } resources: tier: nano timeout: 120 testcases: tests/static_support.json # optional path to JSON test cases| Field | Type | Required | Notes |
|---|---|---|---|
handler | string | mode A only | module:function. Module-level functions only — see handlers. |
entrypoint | list[string] | modes B/C only | argv list, non-empty. The container runs entrypoint[0] entrypoint[1] .... |
description | string | no | Free text. |
inputs | object | no | Typed input ports. See typed I/O. |
outputs | object | no | Typed output ports. |
resources | object | no | Per-function override of package.resources. |
testcases | string | no | Path (relative to repo root) of a JSON file with test cases — read at deploy when quality.validation_testcases.on_deployment is true. |
handler and entrypoint are mutually exclusive at the model level
(can’t have both, must have one). The cross-check against
runtime.kind happens after parsing — mode A requires handler,
modes B/C require entrypoint.
In mode A you can leave inputs: / outputs: out entirely — MecaPy
introspects the handler’s signature and infers them from type hints.
You only declare them when you want to override or document. In modes
B/C they are mandatory because there’s no Python signature to read.
resources
Section intitulée « resources »Two ways to declare resources, mutually exclusive within the same block:
Tier shortcut
Section intitulée « Tier shortcut »resources: tier: nano # one of: nano, micro, small, medium, large timeout: 60 # optional, overrides the tier's timeout| Tier | CPU | Memory (MiB) | Timeout (s) |
|---|---|---|---|
nano | 1 | 512 | 60 |
micro | 1 | 1024 | 120 |
small (default) | 2 | 2048 | 300 |
medium | 2 | 4096 | 600 |
large | 4 | 8192 | 1800 |
large is the platform hard cap. Asking for more in cpu,
memory_mb, or timeout (below) raises a validation error.
Explicit values
Section intitulée « Explicit values »resources: cpu: 2 memory_mb: 1500 timeout: 90cpu and memory_mb may both appear, neither, or just one — but
neither can coexist with tier: in the same block.
Inheritance
Section intitulée « Inheritance »package.resources sets the default. Each function may override with
its own resources: block. The merge follows three rules:
- If the function declares
tier:, it fully selects CPU/memory from that tier — package-level cpu/memory_mb are dropped. - If the function declares
cpu:and/ormemory_mb:, those become authoritative for the fields they cover; the other explicit field, when missing, is inherited from the package (unless package was tier-mode, in which case the function must provide both). timeout:is independently overridable at any level.
Missing both blocks falls back to the platform default (tier: small).
A free-form dict. Today’s only consumer is testcase gating:
quality: validation_testcases: on_deployment: true # run testcases at deploy time fail_on_error: false # block deploy on test failure (default false)When on_deployment: true, the deploy route loads each function’s
testcases: JSON file and runs the cases. Per-function status is
surfaced in the deploy response. With fail_on_error: true, a failing
case turns the deploy into a 4xx; otherwise the deploy completes and
the failed cases are reported as warnings.
The block is intentionally untyped at the model level so new sub-keys
can land without bumping the manifest format. Anything outside
validation_testcases is currently ignored.
Validation order
Section intitulée « Validation order »The parser runs in this order — knowing the order helps when reading error messages:
- YAML load — syntax errors here come from
pyyaml. - Pydantic schema — type-checks every field per the model.
- Discriminated runtime resolution —
runtime.kindselects which sub-model parses the rest of the runtime block. handlerXORentrypoint— function-level model validator.- Cross-check
runtime.kind↔ per-function field — manifest-level validator (validate_manifest_modes). - Resources caps — every
resources:block must respectlarge-tier limits. - Typed I/O resolution — every
type:is looked up in the type catalog; unknown types fail. - Mode A signature introspection (deploy-time only) — the handler is imported and its signature read for type-hint-based schemas.
Errors in steps 1–7 are returned synchronously as 4xx by the deploy
route. Step 8 errors fall back to a permissive {"type": "object"}
schema with a warning logged server-side rather than failing the
deploy outright.