feat(prepare): add dependency ordering to prepare steps#8401
Conversation
Add `depends` field to prepare provider config, allowing providers to declare dependencies on other providers. Uses Kahn's algorithm (same pattern as tool_deps.rs) to schedule providers in topological order with cycle detection and failure propagation. When no providers have depends, the existing parallel execution path is used unchanged. When depends are present, a dependency-aware scheduler runs providers as their dependencies complete. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Summary of ChangesHello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! This pull request significantly enhances the Highlights
Changelog
Activity
Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here. You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension. Footnotes
|
There was a problem hiding this comment.
Code Review
This pull request introduces dependency management for prepare steps, which is a significant and well-implemented feature. The changes include adding a depends field to the configuration, implementing a dependency scheduler using Kahn's algorithm with cycle detection, and preserving the existing parallel execution for projects without dependencies. The new logic is well-tested with both unit and end-to-end tests. My only suggestion is to improve the error handling in one spot to make the code more robust against potential panics.
| } | ||
|
|
||
| Ok(PrepareResult { steps: results }) | ||
| Ok(Arc::try_unwrap(results).unwrap().into_inner().unwrap()) |
There was a problem hiding this comment.
Using unwrap() here can lead to a panic if the Arc has more than one strong reference or if the Mutex is poisoned. While this might be unlikely in the current control flow, it's safer to handle these potential errors gracefully by propagating a Result instead of panicking.
Arc::try_unwrap(results)
.map_err(|_| eyre!("Failed to unwrap Arc for prepare results"))?
.into_inner()
.map_err(|p| eyre!("Prepare results mutex was poisoned: {p:?}"))|
bugbot run |
Greptile SummaryAdded dependency ordering support to prepare providers using Kahn's algorithm scheduler with cycle detection and failure propagation. Key changes:
Testing:
Confidence Score: 5/5
Important Files Changed
Flowchart%%{init: {'theme': 'neutral'}}%%
flowchart TD
A[PrepareEngine.run] --> B{Check if any<br/>providers have depends}
B -->|No deps| C[run_parallel<br/>Simple parallel execution]
B -->|Has deps| D[run_with_deps<br/>Dependency-aware execution]
D --> E[Filter deps:<br/>Remove satisfied/unknown]
E --> F[PrepareDeps.new<br/>Build dependency graph]
F --> G[Detect cycles]
G --> H[Block cyclic providers]
H --> I[PrepareDeps.subscribe<br/>Get receiver channel]
I --> J[emit_leaves<br/>Find ready providers]
J --> K{tokio::select loop}
K -->|Task completes| L{Success or failure?}
L -->|Success| M[complete_success<br/>Remove from graph]
L -->|Failure| N[complete_failure<br/>Block dependents]
M --> J
N --> J
K -->|Receive ready provider| O[Spawn task with semaphore]
O --> K
K -->|Receive None| P[All done - exit loop]
P --> Q[Wait for in-flight tasks]
Q --> R[Return results]
C --> R
Last reviewed commit: 6d4177d |
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace unwrap() on Arc::try_unwrap and Mutex::into_inner with proper error propagation to avoid potential panics. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…deps" This reverts commit c8f7a01.
When using depends, failed providers were logged but silently swallowed, causing exit code 0. Now failures are recorded as Failed results and the function returns an error, matching run_parallel behavior. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add type aliases for complex tuple and Result types used in the dependency-aware execution path. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Wrap task execution in catch_unwind so panics are caught and routed through the normal Ok(Err(...)) path, which calls complete_failure on the dependency graph. Previously a JoinError from a panic would leave the node in the graph, preventing is_all_done from ever returning true and causing the select loop to block forever. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Hyperfine Performance
|
| Command | Mean [ms] | Min [ms] | Max [ms] | Relative |
|---|---|---|---|---|
mise-2026.2.24 x -- echo |
28.2 ± 0.8 | 27.2 | 33.3 | 1.20 ± 0.05 |
mise x -- echo |
23.4 ± 0.7 | 22.4 | 29.8 | 1.00 |
✅ Performance improvement for x -- echo is 20% |
mise env
| Command | Mean [ms] | Min [ms] | Max [ms] | Relative |
|---|---|---|---|---|
mise-2026.2.24 env |
27.9 ± 1.0 | 26.4 | 34.4 | 1.22 ± 0.05 |
mise env |
22.9 ± 0.4 | 22.0 | 24.7 | 1.00 |
✅ Performance improvement for env is 22% |
mise hook-env
| Command | Mean [ms] | Min [ms] | Max [ms] | Relative |
|---|---|---|---|---|
mise-2026.2.24 hook-env |
29.0 ± 0.7 | 27.8 | 33.4 | 1.21 ± 0.03 |
mise hook-env |
23.9 ± 0.4 | 23.0 | 25.4 | 1.00 |
✅ Performance improvement for hook-env is 21% |
mise ls
| Command | Mean [ms] | Min [ms] | Max [ms] | Relative |
|---|---|---|---|---|
mise-2026.2.24 ls |
23.3 ± 0.6 | 22.1 | 26.5 | 1.09 ± 0.04 |
mise ls |
21.3 ± 0.6 | 20.6 | 28.8 | 1.00 |
xtasks/test/perf
| Command | mise-2026.2.24 | mise | Variance |
|---|---|---|---|
| install (cached) | 162ms | 150ms | +8% |
| ls (cached) | 89ms | ✅ 80ms | +11% |
| bin-paths (cached) | 97ms | ✅ 85ms | +14% |
| task-ls (cached) | 829ms | 822ms | +0% |
✅ Performance improvement: ls cached is 11%
✅ Performance improvement: bin-paths cached is 14%
… in failures Extract common Kahn's algorithm scheduling logic from PrepareDeps and ToolDeps into a generic DepsGraph<K, N> struct, eliminating code duplication between the two modules (~435 lines removed). Also fix error details being lost in run_with_deps: previously the returned error only listed failed provider names, now it includes the original error messages for each failure. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add a built-in prepare provider for git submodules that detects .gitmodules and runs `git submodule update --init --recursive` when submodule directories are stale. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…d is_empty - Replace Arc<Mutex<Vec>> with plain Vec for results/errors in run_with_deps since they are only accessed from the main tokio::select! loop - Track inflight task IDs via HashMap<tokio::task::Id, String> to recover provider identity on JoinError (panic/cancellation) and call complete_failure - Remove unused is_empty() methods from PrepareDeps and ToolDeps - Remove duplicate test_is_all_done_empty test from ToolDeps Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
bugbot run |
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
### 🚀 Features - **(hooks)** add task references to hooks and watch_files by @jdx in [#8400](#8400) - **(prepare)** add git-submodule built-in provider by @jdx in [#8407](#8407) - **(prepare)** add human-readable stale reasons to prepare output by @jdx in [#8408](#8408) - **(prepare)** add dependency ordering to prepare steps by @jdx in [#8401](#8401) - **(prepare)** add --explain flag for provider diagnostics by @jdx in [#8409](#8409) - **(prepare)** add per-provider timeout support by @jdx in [#8405](#8405) - **(prepare)** add blake3 content-hash freshness checking by @jdx in [#8404](#8404) - **(tasks)** monorepo vars and per-task vars by @halms in [#8248](#8248) ### 🐛 Bug Fixes - **(aqua)** restore bin_paths disk cache with fresh_file invalidation by @jdx in [#8398](#8398) - **(idiomatic)** use generic parser for idiomatic files by @risu729 in [#8171](#8171) - **(install)** apply precompiled options to all platforms in lockfile by @jdx in [#8396](#8396) - **(install)** normalize "v" prefix when matching lockfile versions by @jdx in [#8413](#8413) - **(prepare)** improve git submodule parser and fix check_staleness error handling by @jdx in [#8412](#8412) - **(python)** respect precompiled settings in lock file generation by @jdx in [#8399](#8399) - **(python)** clarify uv_venv_auto docs + prevent uv shim recursion in venv creation by @halms in [#8402](#8402) - **(task)** remove deprecated `# mise` task header syntax by @jdx in [#8403](#8403) - **(vfox)** avoid eager metadata loading during config file detection by @jdx in [#8397](#8397) - clarify GitHub attestations to be artifact ones by @scop in [#8394](#8394) - ignore comments in idiomatic version files by @iloveitaly in [#7682](#7682) ### 🚜 Refactor - unify archive detection by @risu729 in [#8137](#8137) ### 📚 Documentation - remove duplicated docs for npm.package_manager by @risu729 in [#8414](#8414)
Summary
dependsfield to prepare provider config for declaring inter-provider dependenciesPrepareDeps) with cycle detection and failure propagation, following the same pattern astool_deps.rsdepends, the existing parallel execution path is used unchanged (no regression)Closes #8392 (partial)
TOML syntax
Behavior
depends→ same as today (all independent providers run in parallel)depends = ["uv"]→ waits for "uv" to complete before startingSkippedresult with warningTest plan
prepare_deps.rs— empty graph, no deps, linear ordering, failure blocking, cycle detection, unknown dep error, diamond depstest_prepare_depends— linear dependency ordering, independent parallel execution, dry-runtest_preparepasses (no regression)🤖 Generated with Claude Code
Note
Medium Risk
Adds a new dependency-aware scheduler to
mise prepareand refactors tool installation dependency logic onto shared graph code, which could affect execution ordering and failure handling under concurrency. Backwards-compatible behavior is preserved whendependsis not used, lowering regression risk.Overview
Adds a
dependsfield to prepare provider config (docs + JSON schema) somise preparecan enforce ordering between providers while still running independent providers concurrently.Updates the prepare engine to switch between the existing parallel execution path and a new dependency-aware scheduler that detects cycles, blocks/skips dependents on failure, and reports a new
Failedstep result (with aggregated errors). Extracts the Kahn-style scheduler into a reusableDepsGraphand refactorsToolDepsto use it, and adds an e2e test covering dependency ordering and dry-run output.Written by Cursor Bugbot for commit d7e7924. This will update automatically on new commits. Configure here.