ibek.manifest.yaml and runtime-lock.yaml#
The two halves of the on-disk vendoring contract: the manifest a pattern folder may carry in the library (what is vendored, and where), and the lock written at the destination root (what was vendored, and its integrity hashes).
For the task recipes see Vendor runtime-support patterns; for the reasoning see ADR 0005.
ibek.manifest.yaml#
Lives at the root of a pattern folder in a library. Optional — a pattern with no manifest is vendored through a synthesised default, described below.
version: 1
vendor:
- src: '.*\.(template|proto|protocol|db|req|ibek\.support\.yaml)$'
dest: config
Key |
Meaning |
|---|---|
|
Manifest format version. Only |
|
An ordered, first-match-wins allow-list of rules. At least one is required. |
|
A regular expression matched against a file’s path. |
|
Where the matched file lands, relative to the destination root. |
Unknown keys — at the top level or inside an entry — are rejected. That is what
version: exists to make survivable: a manifest written for a future ibek fails
loudly rather than being read with half its meaning dropped.
src#
Matched with re.fullmatch against the file’s /-joined path relative to
the pattern folder root. Fullmatch rather than search, so src: config cannot
surprise anyone by also matching myconfig/x.template.
Files only. Directories are never matched, so a rule cannot select a folder;
it selects the files inside it (src: 'docs/.*').
The list is ordered and the first matching rule wins. A broad rule placed before a specific one therefore shadows it.
The manifest is an allow-list: a file matched by no rule is simply not
vendored. ibek.manifest.yaml itself is never vendored, regardless of what
matches it.
dest#
Three forms:
A plain folder. Joined with the source’s path relative to the pattern root, so nesting is preserved: with
dest: config,foo/bar.templatelands atconfig/foo/bar.template. This is the form a services repo needs, and the only one the how-to mentions. Adestis a folder when its last part has no file extension or when it ends in/(config/db.d/).A plain file. A
destwhose last part has a file extension and does not end in/(config/renamed.template) is the destination path of the one file the rule matches. A rule of this form that matches more than one file is refused, as two files with one destination.A substitution. Detected by the presence of a
\1-style or\g<name>backreference. The expansion (match.expand) produces the whole destination-relative path, which gives flattening, renaming and re-rooting:vendor: - src: '(?:.*/)?(.*\.proto)' dest: 'config/\1' # flatten every .proto into config/
dest is always relative to the destination root — the folder you point
ibek pattern add at — not to config/. config is simply the conventional
value for an IOC instance, because that folder is the Kubernetes ConfigMap
payload that reaches the container.
No manifest#
A pattern with no ibek.manifest.yaml is vendored through this default
manifest, supplied by ibek itself:
version: 1
vendor:
- src: '.*'
dest: config
It is parsed, validated and compiled by the same code as a real manifest, so there is no second code path and no branch anywhere downstream.
Validation#
The whole manifest is validated, and the complete plan resolved, before a single file is written, so a bad entry cannot leave a half-vendored tree. Every failure names the offending entry (and, where relevant, the offending file) and aborts — nothing is skipped with a warning, because a skipped entry means a file that should be in the IOC silently is not.
Rejected |
Why |
|---|---|
|
The manifest means something this ibek does not know. Checked first, so a manifest from a future ibek is reported as a future manifest and not as an illegal key. |
An empty or missing |
A manifest that vendors nothing is a mistake, not a policy. |
A |
The same mistake, one character further on. Left to run, it prunes every file the pattern had, records |
An unknown key, anywhere |
See |
A |
Fails before any destination is resolved. |
An absolute |
A pattern may only write inside the destination. |
|
Checked after substitution as well as before, since a capture group can introduce one. |
A symlink anywhere in the pattern folder |
Not followed, not vendored, not hashed — including the pattern folder itself, the manifest, and anything inside a folder no rule matches, so one cannot be smuggled in by excluding it. |
A vendored |
|
Two source files producing the same destination |
One would silently overwrite the other, and the lock would record two hashes for the file that survived. Destinations are compared in normal form, so |
One destination inside another ( |
A path cannot be both a file and a folder; discovered during the write it would leave a half-vendored tree. |
Note
ibek runtime place-files copies *.proto / *.protocol / *.db /
*.template into the IOC’s runtime search path from the config/ root only.
Nesting those under config/ is fine for repo organisation and is faithfully
vendored and checked, but they will not be placed at boot.
runtime-lock.yaml#
Written at the destination root (never inside config/), and committed.
version: 1
patterns:
lakeshore340:
version: 1.2.0
source: github.com/epics-containers/ibek-runtime-streamdevice
files:
config/lakeshore340.proto: sha256:...
config/lakeshore340.ibek.support.yaml: sha256:...
Key |
Meaning |
|---|---|
|
Lock format version: |
|
Vendored patterns by name, emitted in name order so re-writing the same set produces no diff. |
|
The pinned upstream tag. |
|
The scheme-stripped library label the pattern came from. |
|
Optional. This instance’s |
|
|
Keys are relative to the destination root, always — config/x.proto, not
x.proto. The synthesised default (a pattern with no manifest) produces
config/... keys naturally, so there is no per-pattern base field and no
branch in check.
The recorded digest is over the library’s bytes verbatim: nothing is injected
or rewritten on the way in, so check is a plain sha256(file) == lock and
diff -r <dest>/config/ <library>/<pattern>/ is empty for a clean instance.
A file entry whose value begins with DIRTY (conventionally
DIRTY # <reason>) is a sanctioned, visible divergence: check warns rather
than fails, without needing --allow-dirty.
Warning
ibek reads and writes exactly the version: / patterns: shape above, and
refuses any other top-level key.
add, update and check all refuse a runtime-lock.yaml in any other
shape, with a generic message naming a conversion script — see
the vendoring how-to.