-
Notifications
You must be signed in to change notification settings - Fork 256
Description
Description
When a remote config file uses extends to load another config file, the job execution order is reversed compared to what would be expected. Jobs from the extending file are executed before jobs from the extended (base) file, which breaks dependency chains.
Steps to Reproduce
Create two config files in a remote repository:
lefthook.yml (base config):
templates:
remote-dir: .git/info/lefthook-remotes/hooks-main
use-mise: eval "$(mise -C {remote-dir} env)"
pre-commit:
jobs:
- name: setup mise
run: |
cd {remote-dir}
mise trust -q
mise install
- name: hooks
group:
parallel: true
jobs:
- name: ggshield
run: |
{use-mise}
{remote-dir}/scripts/ggshield.shlefthook-prettier.yml (extending config):
extends:
- lefthook.yml
pre-commit:
jobs:
- name: hooks
group:
jobs:
- name: prettier
glob: "*.{js,ts,jsx,tsx}"
run: |
{use-mise}
prettier --check {staged_files}Project's lefthook.yml:
remotes:
- git_url: https://github.com/org/hooks
ref: main
configs:
- lefthook-prettier.ymlExpected Behavior
Jobs should execute in this order:
setup mise(from base config)hooksgroup withggshieldandprettierin parallel
Actual Behavior
Jobs execute in this order:
hooksgroup withggshieldandprettierin parallelsetup mise
This breaks the dependency chain because prettier and ggshield require mise to be set up first.
Verification
lefthook dumpOutput shows jobs in reversed order:
pre-commit:
jobs:
- name: hooks
group:
parallel: true
jobs:
- name: prettier
...
- name: ggshield
...
- name: setup mise
...Root Cause
The issue is in internal/config/load.go in the mergeJobsSlice function (lines 506-593).
When merging jobs:
- Line 510-522: Jobs from
dest(already loaded config) are added to result first - Line 524-590: Jobs from
src(new config being merged) are added after
In the context of extends within loadRemotes (line 229-232):
k(dest) containslefthook-prettier.yml(loaded first)lefthook.yml(src, via extends) is merged intok- Result:
lefthook-prettier.ymljobs come beforelefthook.ymljobs
The merge order is: dest → src, but for extends we need: src (base) → dest (extending).
Workaround
Don't use extends in remote configs. Instead, load both configs explicitly in the correct order:
remotes:
- git_url: https://github.com/org/hooks
ref: main
configs:
- lefthook.yml # Base config (loaded first)
- lefthook-prettier.yml # Extension (loaded second)Why this works: When configs are loaded explicitly in sequence without extends, they are merged in the order specified, preserving the correct job execution order.
Impact
Makes extends unusable in remote configs when job ordering matters.
Potential solution
See #1217 but be wary, I have my doubts on relevance of this change.
We might need to find an other solution to order jobs.