mise tasks validate 使用指南:一站式校验任务配置中的依赖环、缺失引用与非法参数
【免费下载链接】misedev tools, env vars, task runner项目地址: https://gitcode.com/GitHub_Trending/mi/mise
本篇技术指南聚焦 mise 的任务静态校验命令mise tasks validate,它在不执行任何任务的前提下,扫描项目全部或指定任务的定义,检查依赖环、缺失引用、超时格式、别名冲突、文件存在性、glob 模式合法性等常见问题。读完本文,你将掌握该命令的全部参数与输出格式,理解其底层十类检查的实现原理,并能在 CI 中用它拦截错误的任务配置。
命令概览
- 命令:
mise tasks validate [--errors-only] [--json] [TASKS]… - 副作用:只读(read-only),不会修改任何文件,也不会执行任务本身
- 实现位置:
src/cli/tasks/validate.rs
该命令用于“校验任务中常见的错误与问题”(Validate tasks for common errors and issues)。它与mise run的主要区别在于:run会真正调度并执行任务,遇到环或缺失引用时在运行中途失败;而validate在运行前完成同样的依赖图构建检查,并额外执行十余项静态规则扫描,让你在开发或 CI 阶段就能发现隐患。
参数(Arguments)
[TASKS]…— 要校验的任务列表。不指定时,校验全部任务。
指定任务时,名称的解析与运行时的任务匹配保持一致:既支持任务名,也支持任务的display_name与别名(alias)。若传入的名字不存在,命令会直接报错并列出当前可用任务名(见 get_specific_tasks)。
标志(Flags)
| 标志 | 说明 |
|---|---|
--errors-only | 仅显示错误(Error),跳过警告(Warning) |
--json | 以 JSON 格式输出校验结果 |
-h, --help | 打印帮助信息 |
基本用法示例
校验全部任务:
mise tasks validate只校验指定任务(可传多个):
mise tasks validate build test以 JSON 格式输出结果:
mise tasks validate --json只显示错误、忽略警告:
mise tasks validate --errors-only退出码语义
从run()的实现 可以看到,只要存在任何Error级别的问题,命令最终就会以非零状态退出并打印Validation failed with N error(s)。因此mise tasks validate可以直接放进 CI 脚本作为门禁:
mise tasks validate --errors-only若只想让任务配置合法即可通过,则使用完整校验;若项目尚存未修复的警告(例如脚本文件没有可执行权限),可以用--errors-only忽略它们。
校验结果输出
人读格式(默认)
当没有任何问题时,输出绿色成功提示:
✓ All 3 task(s) validated successfully当存在问题时,输出会先打印汇总行(如2 task(s) validated with 1 issue(s)),并分别用红色✗标注 Error 数量、黄色⚠标注 Warning 数量,随后按任务分组逐条列出问题,每条问题包含消息与类别标签(category),详情行缩进展示(见 output_human):
2 task(s) validated with 1 issue(s): ✗ 1 error(s) Task: invalid ✗ Dependency 'nonexistent' not found [missing-dependency] Referenced in 'depends' but no matching task existsJSON 格式
--json输出结构由ValidationResults定义:
{ "tasks_validated": 2, "errors": 1, "warnings": 0, "issues": [ { "task": "invalid", "severity": "error", "category": "missing-dependency", "message": "Dependency 'nonexistent' not found", "details": "Referenced in 'depends' but no matching task exists" } ] }字段说明:
tasks_validated:实际参与校验的任务数量;errors/warnings:按严重级别统计的问题数量;issues:问题明细数组。其中severity取值error/warning(序列化时为小写);category是机器可读的类别标签;details仅在存在时输出。
该结构非常适合被脚本、CI 或 LLM 解析。
十类校验检查详解
validate命令在依赖图层面与任务字段层面共执行十类检查(帮助文本见 AFTER_LONG_HELP)。
1. 循环依赖(Circular Dependencies)
检测任务依赖图中的环。校验阶段会调用Deps::new_for_validation构建与运行时一致的依赖图(由depends、depends_post、wait_for共同构成),并基于 petgraph 的 Kosaraju 强连通分量算法检测环(见 find_cycles / new_with_cycle_limit)。
发现环时报错信息形如:
✗ Circular dependency detected [circular-dependency] circular dependency detected: a -> b -> a值得注意的细节(均有 e2e/tasks/test_task_validate 测试佐证):
wait_for参与成环判定:a依赖b、b又wait_fora会被判为环,且mise run a在运行时也会以相同消息拒绝执行;- usage 模板展开后成环也能被捕获:
b的depends使用{% if usage.enabled %}a{% endif %}模板,校验时会先渲染 usage 默认值再构图,从而发现环; - 环的去重报告:同一环只报一次。代码用
canonical_cycle对环做规范化(旋转取最小表示),并维护reported_cycles集合去重,见 push_cycle_issue / canonical_cycle; - 不同环境值下相同的任务名不算同一环:
TaskKey中包含了名称、参数、环境变量与执行阶段(见 deps.rs 的 task_key),单测cycle_identity_includes_environment_values验证了这点; depends_post会创建独立的 post 阶段:a通过depends_post = ["b"]引用b、而b又depends = ["a"]时不是环——因为a会先在 normal 阶段运行一次,再作为b的 post 阶段前置任务运行,测试验证了mise run a输出a a b。
2. 缺失引用(Missing References)
查找对不存在任务的引用。检查范围覆盖三类依赖字段:
dependsdepends_postwait_for
对应源码 validate_missing_references 的实现细节:
- 对每条依赖,若指向的任务不存在,报
missing-dependency错误,并注明引用来源(如Referenced in 'depends' but no matching task exists); - 可选项跳过:标记为 optional 的依赖不参与此项检查(其选择器合法性仍由依赖图构建保证);
- 通配符跳过:含
*或?的模式依赖在运行时才解析,此处不报缺失; - monorepo 相对引用按运行时规则解析:
task_exists使用resolve_task_pattern+build_task_ref_map,因此_dep bare、:_dep colon、//pkg:_dep full、以及按别名引用都能被正确匹配(见 e2e 测试中 monorepo 用例)。
3. Usage Spec 解析(Usage Spec Parsing)
校验任务的#USAGE指令与 usage spec 是否合法,对应 validate_usage_spec:
- 尝试用
parse_usage_spec_for_display解析任务的 usage spec,解析失败报usage-parse-error警告并附上解析器错误信息; - 若任务的
usage字段里直接出现了#USAGE/# USAGE指令标记,则报usage-directive警告,提示该字段应直接书写 spec 内容而不是指令本身。
usage 语法错误还可能导致依赖图构建失败(例如depends中使用了无法解析的{{usage.target}}模板),此时归类为dependency-graph-error错误(测试中有专门用例)。
4. 超时格式(Timeout Format)
校验timeout字段是否为合法时长,对应 validate_timeout。超时值支持30s、5m、1h等格式,并支持 Tera 模板(见 task-configuration.md 的 timeout 一节)。解析失败时报invalid-timeout错误,例如:
[tasks.bad-timeout] run = "echo test" timeout = "not-a-duration"会输出Invalid timeout format: 'not-a-duration'。
5. 别名冲突(Alias Conflicts)
检测任务别名之间的重复,以及别名与任务名的冲突,对应 validate_aliases。规则如下:
- 同一别名被多个任务使用时,报
alias-conflict错误,消息形如Alias 'myalias' is used by multiple tasks,details 列出涉及的任务; - 每个冲突只报告一次:只按字母序第一个任务报告,避免每个任务都报一遍(e2e 测试专门断言错误计数为 1);
- 别名与某个任务名同名时,同样报
alias-conflict错误; - 同一个任务同时定义
alias与aliases字段,属于文件任务解析层的错误(消息Cannot define both 'alias' and 'aliases',见 e2e 用例)。
6. 文件存在性(File Existence)
校验基于文件的任务(file task)中file字段指向的脚本,对应 validate_file_existence:
- 文件不存在:报
missing-file错误(Task file not found: <path>); - 文件存在但不可执行:报
not-executable警告,并附上chmod +x修复提示(该提示文案在 Windows 上不同,e2e-win 有对应断言)。
7. 目录与目录模板(Directory Templates)
校验任务dir字段,对应 validate_directory:
- 若
dir含模板语法(如{{...}}),尝试渲染模板:- 渲染失败:报
invalid-directory-template错误; - 渲染成功但目录不存在:报
missing-directory警告;
- 渲染失败:报
- 若
dir是静态绝对路径且不存在:报missing-directory警告。
8. Shell 命令存在性(Shell Commands)
校验shell字段指定的 shell 可执行文件是否存在,对应 validate_shell。shell可以是"bash -c"或"bash"这种带参数的形式,代码取第一个词(可含绝对路径)检查:若是绝对路径且文件不存在,报invalid-shell错误。注意:仅针对绝对路径做存在性检查,裸命令名交由 PATH 在运行时解析。
9. Glob 模式(Glob Patterns)
校验sources与outputs中的 glob 模式是否为合法正则语法,对应 validate_source_patterns 与 validate_output_patterns:
- 使用
globset::GlobBuilder编译每个模式,编译失败报invalid-glob-pattern错误; - 取反前缀处理:
sources中以!(取反)或\!(转义)开头的模式,先剥离前缀再校验。因此!src/**/*.test.ts这类合法排除写法不会被误报,而!{[bad这类剥离前缀后仍然非法的模式会被正确报错(e2e 用例覆盖了正反两种情况); outputs中的每个模式同样用GlobBuilder校验。
10. Run 条目(Run Entries)
校验任务run定义中的内嵌任务引用,对应 validate_run_entries,覆盖三种RunEntry形态:
- 脚本(Script):脚本内容为空白时报
empty-script警告; - 单任务(SingleTask):如
{ task = "test --mode=integration" },先剥离内联参数再检查任务是否存在(与运行时行为一致),不存在报missing-task-reference错误; - 并行任务组(TaskGroup):如
{ tasks = ["test --mode=integration", "test --mode=unit"] },逐条剥离参数后检查,缺失时报错并注明Referenced in parallel task group。
此外还有一个兜底规则:若任务既没有 run 条目、也没有file,且没有depends/depends_post(即没有任何可执行内容),报no-execution错误,提示Task must have either 'run', 'run_windows', 'file', or 'depends' defined。纯依赖聚合型任务(meta/group task)因为有depends,不会触发该错误。
底层实现:依赖图与校验流水线
mise tasks validate的执行流程(run())可以分为四步:
- 加载配置与远程任务:通过
Config::get()获取配置,列出全部任务;随后用TaskFetcher预取远程任务文件(如 git/HTTP 来源的任务),确保远程任务能被正确校验,同时仍尊重MISE_TASK_REMOTE_NO_CACHE环境变量(命令本身不提供--no-cache参数); - 构建依赖图:用
Deps::new_for_validation构建完整依赖图,该图与mise run运行时构图逻辑一致(节点键为TaskKey = (名称, 参数, 环境变量, 阶段))。若构图失败:- 是环:记录环路径后,
find_additional_graph_issues会继续逐个任务单独构图,找出其余未被首个错误掩盖的环与图错误,避免一个问题掩盖一片问题; - 是其他图错误:报
dependency-graph-error,并通过去重保证同一错误只报告一次; - 组合场景验证:
wait_for只作用于同时被选中的任务之间,因此“两个任务单独构图都能成功、合并构图才成环”的情况会在最后一步被捕获(见 find_additional_graph_issues);
- 是环:记录环路径后,
- 逐任务字段检查:对每个任务依次执行缺失引用、usage spec、timeout、别名、文件、目录、shell、glob、run 条目共九项检查(见 validate_task);
- 输出与退出:按
--errors-only/--json处理结果,存在 Error 时以非零状态退出。
这一设计与端到端测试 e2e/tasks/test_task_validate 完全对应——测试覆盖了成功场景、环检测(含wait_for成环、usage 模板展开成环)、多图并发错误不互相掩盖、别名冲突去重、缺失依赖、非法/合法超时、非法 glob、取反模式、JSON 输出、--errors-only、按别名校验、文件任务未知字段、monorepo 引用解析等大量场景。
与相关文档的衔接
- 任务配置的全部属性(
run、depends、depends_post、wait_for、timeout、shell、sources、outputs、file、alias等)参见 任务配置参考; - 任务的入门定义与 TOML 任务写法参见 任务总览 与 TOML 任务;
- 依赖执行顺序、通配符与并行组语义参见 运行任务;
- monorepo 下任务跨项目根解析(
//pkg:task语法)参见 Monorepo 任务; - 其他任务子命令(
ls、run、info、graph、deps、edit、add)位于 docs/cli/tasks 目录下。
小结
mise tasks validate是任务配置的“静态分析器”:它复用与运行时完全一致的依赖图构建逻辑,因而能提前发现mise run才会暴露的环与缺失引用;同时它对 timeout、glob、usage spec、别名、文件与 shell 等字段做细粒度检查,并以人性化或 JSON 两种格式输出、以退出码表达校验结果。建议将mise tasks validate(CI 中可加--errors-only)纳入提交前检查或持续集成流水线,让任务定义在团队协作与 CI 中始终保持可执行、可预期。
【免费下载链接】misedev tools, env vars, task runner项目地址: https://gitcode.com/GitHub_Trending/mi/mise
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考