feat: !include YAML tag and folder-based workflow layout #584
Reference in New Issue
Block a user
Delete Branch "feat/include-and-folder-workflow"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Changes
!include YAML tag (Fixes #582)
!include path/to/filecustom YAML tag,加载时替换为文件内容.md/.txt→ string,.json→ parsed JSON,.yaml/.yml→ parsed YAMLpackages/cli-workflow/src/include.tsFolder-based workflow layout (Fixes #583)
foo/index.yaml表达 name 为foo的 workflowdiscoverProjectWorkflows()、findWorkflowInDir()、workflowNameFromPath()Tests
!includetag 测试Review by 小橘 🍊(NEKO Team)
Overall solid PR — clean functional style, good test coverage (6 include + 2 folder tests), conventions followed. A few observations:
Issues
1. Nested
!includein YAML files won't workinclude.ts:21— when an included.yamlfile itself contains!includetags, they won't resolve becauseparseYaml(content)is called without passingcustomTags. Should be:This would also correctly resolve relative paths from the included file's directory.
2. No path traversal guard
!include ../../etc/passwdwould happily read arbitrary files. Consider validating that the resolved path stays within (or at least under)baseDir:Minor
readFileSyncin the tag resolver is acceptable since YAML'scustomTags.resolveis synchronous — just noting it's a conscious tradeoff.discoverProjectWorkflowsonly scans.workflows/for folder layout butfindWorkflowInDiralso checks.workflow/. Intentional asymmetry? The.workflow/variant isn't discoverable viauwf workflow listif so.Verdict
The nested include bug (#1) should be fixed before merge. Path traversal (#2) is a nice-to-have hardening. The rest looks good — folder priority logic is correct,
workflowNameFromPathhandlesindex.yamlcleanly, tests are well-structured.Re-reviewed all 3 fixes — everything looks good! ✅
Nested
!include:createIncludeTagnow recursively passescustomTagswithbaseDirswitched todirname(filePath)for included YAML files. New test confirms nested include resolution.Path traversal guard:
resolve()is called first, then the result is checked againstresolvedBase + "/". Both../and absolute path attacks are blocked. Two new tests cover this.Directory scan consistency:
discoverProjectWorkflowsscans both.workflow/(primary) and.workflows/(legacy), with.workflow/entries taking priority via aSet-based dedup. Test confirms.workflow/wins over.workflows/.LGTM 🍊
— 小橘 🍊(NEKO Team)