Repository navigation
feat(manifest): add template directives, indent-aware substitution and comma join - #28
Merged
Merged
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Template directives (manifest
schemaVersion5). Templates and fragments can wrap lines in comment directives written in the file's own comment syntax, so the template stays valid YAML, Dockerfile or Markdown:The branch that doesn't apply and all directive lines are removed before fragments and placeholders are rendered. A condition is a config path declared in a preset's
configKeys.true, a non-empty string or a non-empty array count as true; unset,false,""and[]count as false. Directives also work on files without arenderblock.Errors surface when the preset chain resolves, before anything is written, and name the file and line (
presets/<source>:<line>: …). This covers broken nesting, mismatchedend/elsenames, YAML bodies indented less than their directive, undeclared or object-valued conditions, directives in JSON ormergefiles, and directives in payloads belowschemaVersion5 (where otherstreamctl:comments stay plain content). Every template is checked, including files switched off or disabled byenabledBy.Indent-aware substitution. Extra lines of a multi-line placeholder value get the indentation of the line holding the token, so
run: |blocks stay valid. Tokens at column 0 render exactly as before.Placeholders are only resolved when their token is reachable from the rendered text, directly or through another value. A token inside a dropped block, or a declared placeholder nobody uses, no longer fails the render through its
pattern.join: "comma"(schema 5) rendersstring[]placeholders asdev, main. It skips the shell-metacharacter check thatspaceapplies, since the value isn't going into a shell;patternis the guard.initruns its first sync with the scaffoldedstreamctl.config.tsinstead of a bare{ package, base, version, profile }, so payload wrapper defaults apply from the start. If the file can't be loaded, it warns once and falls back to the old behavior.scanDirectives,commentSyntaxFor,DIRECTIVES_MIN_SCHEMA_VERSIONandCOMMA_JOIN_MIN_SCHEMA_VERSIONare exported from@sidebase/streamctl/manifest, so payloads can lint their templates in their own CI.v2 to v4 payloads parse unchanged and render the same, except that multi-line placeholder values on indented lines are now indented (see release notes). Docs are in the README,
docs/reference.mdand the release notes indocs/release.md.Why
Payloads needed per-consumer variation inside a single file: a CI step only some repos want, a Dockerfile stage behind a feature switch. The only options were
enabledBy(whole file on or off) or fragments appended at the end, which can't put a step in the middle of a job. Comment directives give conditional blocks at any position without breaking the template's own syntax, so editors, linters andvalidateStructuredkeep working on the source.Conditions are config paths only, not dependency or file checks. Version reconcile adds baseline pins to every consumer, so "has dependency X" ends up true everywhere. An explicit switch in the config, with its default set by the payload's config wrapper, is the reliable signal. That's also why
initnow has to load the scaffolded config: without it the first sync ignores those defaults.Minor bump: new schema version, no removals.