Skip to content

wmill script generate-metadata emits unquoted summary/description → a ' #' silently truncates the value on push #10237

Description

@cloudsavant

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.tsgenerateMetadata() (~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.

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions