What happened
wmill script generate-metadata writes the summary: / description: fields of a *.script.yaml as unquoted YAML plain scalars. When such a value contains a # preceded by whitespace — e.g. an issue reference like (C2 of #777) — the emitted file is not round-trip-safe: a spec-compliant YAML parser treats #777) as a start-of-comment and silently truncates the value.
This bites in practice because the Windmill backend (serde_yaml) parses the metadata differently from the JS yaml lib that wrote it, so the deployed summary/description ends up truncated at the first #, with no error on push and nothing visibly wrong in an editor. It only shows up if you diff the parsed value.
Minimal repro
# any script whose summary contains a whitespace-preceded '#'
cat f/demo/x.script.yaml
# -> summary: My collector — incremental facts (#779, C2 of #777) # unquoted
python3 -c 'import yaml; print(repr(yaml.safe_load(open("f/demo/x.script.yaml"))["summary"]))'
# -> 'My collector — incremental facts (#779, C2 of' <-- everything from ' #777)' is gone
The same truncation occurs with any spec-compliant parser (PyYAML, js-yaml, serde_yaml). A # not preceded by whitespace ((#779), myproject#42) is fine — only # triggers it.
Impact
- Silent, plausible data loss: the truncated value is still valid YAML, so push reports success. Deployed script summaries/descriptions are quietly cut off in the UI and in
wmill script show.
- Hits essentially any repo that references issues/PRs in summaries (
… #NNN …), which is common.
- Because it's
generate-metadata output, re-running the command re-introduces it even after a manual fix.
Where
cli/src/commands/script/script.ts — generateMetadata() (~L1341) serializes via yamlStringify(...) (~L1316, import { stringify as yamlStringify } from "yaml"). The emitted plain scalar for summary / description isn't guaranteed round-trip-safe under strict parsers.
Suggested fix
Force these string fields to be emitted quoted (or otherwise round-trip-safe) rather than as bare plain scalars — e.g. pass a yaml stringify option that quotes strings needing it, or explicitly quote summary/description. The yaml package can be told to quote via node types / defaultStringType: 'QUOTE_SINGLE' (or per-field), which makes the output safe for every parser including the backend.
Workaround (for anyone hitting this now)
Post-process the generated file to single-quote any summary/description whose parsed value differs from its literal text. Reference implementation (guard + --check/--fix + runbook): a small self-contained tool that re-quotes only genuinely-truncating scalars and leaves correct multi-line folds intact. Happy to upstream the detection logic if useful.
Environment: CLI 1.703.x, backend CE v1.763.0.
What happened
wmill script generate-metadatawrites thesummary:/description:fields of a*.script.yamlas unquoted YAML plain scalars. When such a value contains a#preceded by whitespace — e.g. an issue reference like(C2 of #777)— the emitted file is not round-trip-safe: a spec-compliant YAML parser treats#777)as a start-of-comment and silently truncates the value.This bites in practice because the Windmill backend (serde_yaml) parses the metadata differently from the JS
yamllib that wrote it, so the deployed summary/description ends up truncated at the first#, with no error on push and nothing visibly wrong in an editor. It only shows up if you diff the parsed value.Minimal repro
The same truncation occurs with any spec-compliant parser (PyYAML,
js-yaml, serde_yaml). A#not preceded by whitespace ((#779),myproject#42) is fine — only#triggers it.Impact
wmill script show.… #NNN …), which is common.generate-metadataoutput, re-running the command re-introduces it even after a manual fix.Where
cli/src/commands/script/script.ts—generateMetadata()(~L1341) serializes viayamlStringify(...)(~L1316,import { stringify as yamlStringify } from "yaml"). The emitted plain scalar forsummary/descriptionisn't guaranteed round-trip-safe under strict parsers.Suggested fix
Force these string fields to be emitted quoted (or otherwise round-trip-safe) rather than as bare plain scalars — e.g. pass a
yamlstringify option that quotes strings needing it, or explicitly quotesummary/description. Theyamlpackage can be told to quote via node types /defaultStringType: 'QUOTE_SINGLE'(or per-field), which makes the output safe for every parser including the backend.Workaround (for anyone hitting this now)
Post-process the generated file to single-quote any
summary/descriptionwhose parsed value differs from its literal text. Reference implementation (guard +--check/--fix+ runbook): a small self-contained tool that re-quotes only genuinely-truncating scalars and leaves correct multi-line folds intact. Happy to upstream the detection logic if useful.Environment: CLI 1.703.x, backend CE v1.763.0.