Lefthook Jobs 完全指南:用组(Group)与并行/管道流程编排 Git Hook 任务 Lefthook Jobs 完全指南用组Group与并行/管道流程编排 Git Hook 任务【免费下载链接】lefthookFast and powerful Git hooks manager for any type of projects.项目地址: https://gitcode.com/GitHub_Trending/le/lefthookjobs是 lefthook自1.10.0起引入提供的一种灵活的任务定义方式它统一了run命令与script脚本两种执行载体并支持将多个 job 组合成 group 以实现并行、管道等高级流程控制。本文以 docs/configuration/jobs.md 为骨架结合仓库源码internal/config/job.go、internal/run/controller/*.go深入讲解 jobs 的字段语义、组继承规则、合并策略与底层调度原理读完你将能直接写出可运行的多语言、多目录、多阶段 Git Hook 配置。jobs 是什么在传统的commands/scripts语法里一个 hook 下只能组织两层结构命令集合 单条命令。而jobs允许你以数组形式声明任务每个 job 可以是一个命令run、一个脚本script也可以是一个嵌套的 groupgroup从而表达更复杂的工作流支持在单个 hook 内混用命令、脚本与分组每个 job 拥有独立的root、glob、exclude、tags、env、timeout等选项分组内部可以独立声明parallel或piped流程并作为整体参与外层 hook 的调度。从源码结构看jobs与commands/scripts是并列的两套声明体系。在 internal/config/hook.go 中Hook同时持有Jobs []*Job与Commands/Scripts两个 map二者可以共存。当 hook 声明了jobs时执行控制器会直接以hook.Jobs作为调度单元见 internal/run/controller/controller.go 的RunHook。一个完整的 jobs 示例原文档给出了一个极具代表性的配置一个piped 流水线组与多个独立 job并行执行覆盖了 Ruby、前端、Go 与自定义脚本四种任务# lefthook.yml pre-commit: parallel: true jobs: - name: migrate root: backend/ glob: db/migrations/* group: piped: true jobs: - run: bundle install - run: rails db:migrate - run: yarn lint --fix {staged_files} root: frontend/ stage_fixed: true - run: bundle exec rubocop root: backend/ - run: golangci-lint root: proxy/ - script: verify.sh runner: bash这段配置的运行语义是hook 级别parallel: true四个 jobmigrate组、前端 lint、后端 rubocop、Go lint并发启动其中migrate是一个 group组内piped: true即bundle install→rails db:migrate按顺序执行前一步失败则后续步骤被跳过glob: db/migrations/*与root: backend/在 group 上声明自动作用于组内全部嵌套 job——只有当暂存区包含backend/db/migrations/下的文件时该组才会真正运行。注意script类型 job 需要配套runner此处为bash表示用什么解释器执行脚本文件。job 的字段详解一个 job 的完整字段定义位于 internal/config/job.go 的Job结构体这里结合源码逐一说明字段类型说明namestringjob 名称用于日志输出与--job定向执行未命名时回退显示run内容或script内容runstring要执行的命令支持{staged_files}、{push_files}等模板详见 docs/configuration/run.mdscriptstring要执行的脚本文件路径相对 docs/configuration/root.mdrunnerstring执行脚本的解释器如bash、sh详见 docs/configuration/runner.mdargsstring传给脚本的参数rootstring改变命令执行的工作目录CWDfilesstring自定义文件列表命令替代默认 staged/push 文件fail_textstring命令失败时输出的自定义错误文案timeoutduration超时时间如15s超时按失败处理并提示timeout (15s)globstring / array过滤暂存文件的 glob 模式从 git 仓库根计算不受root影响excludestring / array排除文件的 glob 模式tagsstring / array标签配合--tags或 hook 级exclude_tags使用file_typesstring / array按文件类型过滤详见 docs/configuration/file_types.mdenvmap注入环境变量interactivebool是否以交互式 TTY 执行use_stdinbool是否把 git 提供的 STDIN 数据传给命令详见 docs/configuration/use_stdin.mdstage_fixedbool命令成功后把修复过的文件重新加入暂存区skip/onlybool / array条件跳过或仅运行详见 docs/configuration/skip.md、docs/configuration/only.mdgroupobject嵌套分组内含root、parallel、piped、jobs三选一约束与校验从 internal/run/controller/job.go 可以看到runJob在真正执行前会做严格校验run与script不能同时设置run、script、group三者必须至少提供其一否则直接判定失败错误信息为either \run,script, or group must be provided for a job若group存在但jobs为空则报错group must have \jobs。名称的显示规则PrintableNameinternal/config/job.go决定了日志中 job 的显示名优先用name其次用run内容再其次用script都没有时退化为[序号]。嵌套时日志会以组名 ❯ job名的形式展示层级。命名 job 的合并策略原文档明确了两条合并规则命名 job有name会在 extends 配置与本地配置之间进行合并未命名 job则按定义顺序追加。也就是说当lefthook.yml通过extends引入共享配置、再用lefthook-local.yml覆盖时同名 job 的字段会按层级合并而匿名 job 只增不减保证了顺序语义。配合 docs/configuration/extends.md 中描述的应用顺序lefthook.yml→extends→remotes→lefthook-local.yml你可以把通用检查项下沉到共享配置把项目特有任务追加到本地配置。group嵌套流程控制Group结构体internal/config/job.go只有四个字段type Group struct { Root string Parallel bool Piped bool Jobs []*Job }其中Jobs是必填的嵌套 job 数组Parallel与Piped决定组内调度方式parallel: true组内 jobs 并发执行c.concurrentlypiped: true组内 jobs 严格按顺序执行一旦某个 job 失败后续 job 全部跳过并标记为broken pipe二者都未设置按顺序执行但失败不中断后续任务。组选项的继承规则关键特性是root、glob、exclude三个选项声明在 group 上时会作用于组内所有嵌套 job。原文档特别提醒目前只有这三个选项会被组继承其余选项如env、tags、timeout、file_types等必须逐个 job 单独设置——如果这种限制限制了你的工作流可向项目提交 feature request。从源码看这一继承在 internal/run/controller/scope.go 的scope.extend中实现进入嵌套 group 时newScope会拼接 job 的Glob、Tags、FileTypes用FirstNonBlank覆盖Root与Files并追加Exclude列表。因此组内每个 job 实际拿到的scope都是「父级累积 自身覆盖」的结果。组与 hook 的并行/管道组合外层 hook 同样有parallel与piped见 internal/config/hook.go组可以嵌套在任意层级。调度逻辑在 internal/run/controller/controller.goif hook.Parallel { results c.concurrently(ctx, scope, hook.Jobs) } else { results c.sequentially(ctx, scope, hook.Jobs, hook.Piped) }concurrently为每个 job 启动一个 goroutine通过 channel 收集结果sequentially顺序执行若piped为 true 则维护failPipe标志一旦出现失败后续 job 直接跳过controller.go。而 group 内部同样复用这两个方法job.go所以「外层并行 组内管道」的组合自然成立——这正是原文档示例中migrate组在pre-commit.parallel: true下先跑bundle install再跑rails db:migrate、同时其余 lint 任务并发执行的原因。并行与管道的互斥约束需要留意的是parallel与piped的语义冲突同一层hook 或 group不能同时设置piped: true与parallel: true否则 lefthook 会报错。这两者的关系可以分别参考 docs/configuration/parallel.md 与 docs/configuration/piped.mdpiped表示「失败即停」parallel表示「并发执行」二者天然互斥。正确用法是像示例那样——外层并行把需要严格串行的步骤放进一个piped的 group 里。与--job定向执行的配合jobs 支持通过命令行按名称定向执行。在 internal/run/controller/job.go 中若指定了RunOnlyJobs且当前 job 名称不在其中该 job 直接返回 Skip。scope.extend里还有一个细节如果--job指定的名称恰好是一个 group 的名字该 group 内的所有 job 都会被放行scope.go即「选中组 运行组内全部任务」。实战建议用 group 表达「先安装依赖再执行迁移」这类强依赖步骤piped: true保证前序失败时不会继续浪费时间把无依赖的 lint/format 类检查放在 hook 顶层并行执行缩短整体耗时充分利用 group 级rootglob的继承能力例如「仅在backend/db/migrations/变更时跑迁移」这类按目录过滤的需求只需在组上声明一次为关键 job 设置name一方面让日志可读另一方面获得跨extends的合并能力与--job定向执行能力给脚本类 job 配置正确的runner并为耗时操作设置timeout防止挂死。关于更多字段的细节可继续查阅仓库内 docs/configuration/run.md、docs/configuration/script.md、docs/configuration/glob.md、docs/configuration/root.md、docs/configuration/exclude.md、docs/configuration/tags.md以及参考 examples/complete/lefthook.yml 中的完整配置示例。【免费下载链接】lefthookFast and powerful Git hooks manager for any type of projects.项目地址: https://gitcode.com/GitHub_Trending/le/lefthook创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考