fix(task): resolve vars from subdirectory configs for monorepo tasks#8343
fix(task): resolve vars from subdirectory configs for monorepo tasks#8343
Conversation
When running a monorepo task like `mise run //infra/stacks/gcp:greet` from the repo root, `[vars]` defined in the task's subdirectory configs were not loaded, causing "Variable `vars.MY_VAR` not found in context" errors. Root cause: The tera context used for task script rendering only contained global vars from `config.vars`, not vars from the task's config hierarchy. Additionally, `parse_usage_spec_and_init_env` re-parsed scripts without vars, causing rendering failures. Fix: Resolve vars from the task's config hierarchy in `build_tera_context` and thread them through the script rendering chain via `TaskScriptParser.extra_vars`. Closes #6564 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Summary of ChangesHello @jdx, 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 resolves a critical issue where environment variables defined in 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
|
Greptile SummaryFixes monorepo tasks ( Key Changes:
Impact:
Confidence Score: 4/5
Important Files Changed
Sequence DiagramsequenceDiagram
participant Executor as TaskExecutor
participant ContextBuilder as TaskContextBuilder
participant Task as Task
participant Parser as TaskScriptParser
Note over Executor: Execute monorepo task //path:task
Executor->>ContextBuilder: resolve_task_env_with_config()
activate ContextBuilder
Note over ContextBuilder: Load task config hierarchy<br/>(includes MISE_ENV files)
ContextBuilder->>ContextBuilder: load_config_hierarchy_from_dir()
ContextBuilder->>ContextBuilder: build_tera_context(task_config_files)
Note over ContextBuilder: Resolve vars from hierarchy<br/>Merge with global config.vars
ContextBuilder-->>Executor: (env, task_env, extra_vars)
deactivate ContextBuilder
Executor->>Task: render_run_scripts_with_args(extra_vars)
activate Task
Task->>Task: parse_usage_spec_with_vars(extra_vars)
Task->>Parser: new().with_extra_vars(extra_vars)
activate Parser
Parser->>Parser: inject_extra_vars(tera_ctx)
Note over Parser: Insert vars into {{ vars.* }}
Parser->>Parser: render scripts with vars
Parser-->>Task: (rendered_scripts, spec)
deactivate Parser
Task-->>Executor: rendered scripts
deactivate Task
Executor->>Task: parse_usage_spec_and_init_env(extra_vars)
Note over Executor: Parse again with args<br/>using same extra_vars
Note over Executor: Execute rendered scripts
Last reviewed commit: c45dd9e |
There was a problem hiding this comment.
Code Review
This pull request addresses an issue with variable resolution for monorepo tasks by correctly loading [vars] from subdirectory configs. The approach of threading these variables through the task execution pipeline is sound. I've identified a critical bug where file-based monorepo tasks would still not have access to these variables. Additionally, I've suggested some improvements for the new e2e test and a small refactoring to reduce code duplication.
src/task/task_executor.rs
Outdated
| let args = task.args.iter().cloned().collect_vec(); | ||
| let get_args = || once(command.clone()).chain(args.clone()).collect_vec(); | ||
| self.parse_usage_spec_and_init_env(config, task, &mut env, get_args) | ||
| self.parse_usage_spec_and_init_env(config, task, &mut env, get_args, None) |
e2e/tasks/test_task_monorepo_vars
Outdated
| # Test 2: Subdirectory task sees subdirectory vars (the core bug fix) | ||
| echo "=== Test 2: Subdirectory task sees subdirectory vars ===" | ||
| unset MISE_ENV | ||
| output=$(mise run '//infra/stacks/gcp:greet') | ||
| echo "$output" | ||
| assert_contains "echo '$output'" "GCP_VAR=gcp_value" | ||
| assert_contains "echo '$output'" "SHARED_VAR=from_gcp" | ||
|
|
||
| # Test 3: Subdirectory task still inherits root vars it doesn't override | ||
| echo "=== Test 3: Subdirectory task inherits root vars ===" | ||
| unset MISE_ENV | ||
| output=$(mise run '//infra/stacks/gcp:greet') | ||
| echo "$output" | ||
| assert_contains "echo '$output'" "ROOT_VAR=root_value" | ||
|
|
||
| # Test 4: Subdirectory vars override root vars of the same name | ||
| echo "=== Test 4: Subdirectory vars override root vars ===" | ||
| unset MISE_ENV | ||
| output=$(mise run '//infra/stacks/gcp:greet') | ||
| echo "$output" | ||
| # SHARED_VAR should be from_gcp, not from_root | ||
| assert_contains "echo '$output'" "SHARED_VAR=from_gcp" |
There was a problem hiding this comment.
Tests 2, 3, and 4 each run the same mise run command. For better efficiency and clarity, you could combine these into a single test case that runs the command once and then performs all related assertions.
# Test 2, 3, 4: Subdirectory task var resolution
echo "=== Test 2, 3, 4: Subdirectory task var resolution ==="
unset MISE_ENV
output=$(mise run '//infra/stacks/gcp:greet')
echo "$output"
# Test 2: Subdirectory task sees subdirectory vars (the core bug fix)
assert_contains "echo '$output'" "GCP_VAR=gcp_value"
# Test 4: Subdirectory vars override root vars of the same name
assert_contains "echo '$output'" "SHARED_VAR=from_gcp"
# Test 3: Subdirectory task still inherits root vars it doesn't override
assert_contains "echo '$output'" "ROOT_VAR=root_value"
e2e/tasks/test_task_monorepo_vars
Outdated
| cat <<EOF >infra/stacks/gcp/mise.toml | ||
| [vars] | ||
| GCP_VAR = "gcp_value" | ||
| SHARED_VAR = "from_gcp" | ||
|
|
||
| [tasks.greet] | ||
| run = 'echo "GCP_VAR={{vars.GCP_VAR}} SHARED_VAR={{vars.SHARED_VAR}} ROOT_VAR={{vars.ROOT_VAR}}"' | ||
|
|
||
| [tasks.greet-dev] | ||
| run = 'echo "DEV_VAR={{vars.DEV_VAR}} SHARED_VAR={{vars.SHARED_VAR}}"' | ||
| EOF |
There was a problem hiding this comment.
Instead of overwriting the entire mise.toml file, you could append just the new task definition. This would make the test's intent clearer and avoid re-defining existing configuration.
cat <<EOF >>infra/stacks/gcp/mise.toml
[tasks.greet-dev]
run = 'echo "DEV_VAR={{vars.DEV_VAR}} SHARED_VAR={{vars.SHARED_VAR}}"'
EOF
src/task/mod.rs
Outdated
| let mut parser = TaskScriptParser::new(cwd); | ||
| if let Some(vars) = extra_vars { | ||
| parser = parser.with_extra_vars(vars); | ||
| } |
- Pass extra_vars through exec_file for file-based monorepo tasks - Cache resolved_vars in env_resolution_cache so subsequent tasks sharing the same config path still get vars - Consolidate e2e tests 2/3/4 into a single test case - Extract make_script_parser helper to reduce duplication Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
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.
Hyperfine Performance
|
| Command | Mean [ms] | Min [ms] | Max [ms] | Relative |
|---|---|---|---|---|
mise-2026.2.20 x -- echo |
26.5 ± 0.6 | 25.3 | 32.1 | 1.02 ± 0.05 |
mise x -- echo |
25.9 ± 1.1 | 24.5 | 38.3 | 1.00 |
mise env
| Command | Mean [ms] | Min [ms] | Max [ms] | Relative |
|---|---|---|---|---|
mise-2026.2.20 env |
25.0 ± 0.8 | 23.7 | 34.2 | 1.00 |
mise env |
25.5 ± 0.7 | 23.9 | 27.8 | 1.02 ± 0.04 |
mise hook-env
| Command | Mean [ms] | Min [ms] | Max [ms] | Relative |
|---|---|---|---|---|
mise-2026.2.20 hook-env |
25.8 ± 0.5 | 24.8 | 28.8 | 1.00 |
mise hook-env |
26.2 ± 0.9 | 24.9 | 39.2 | 1.02 ± 0.04 |
mise ls
| Command | Mean [ms] | Min [ms] | Max [ms] | Relative |
|---|---|---|---|---|
mise-2026.2.20 ls |
23.3 ± 0.7 | 22.2 | 27.6 | 1.00 |
mise ls |
24.0 ± 0.5 | 22.6 | 25.8 | 1.03 ± 0.04 |
xtasks/test/perf
| Command | mise-2026.2.20 | mise | Variance |
|---|---|---|---|
| install (cached) | 158ms | 159ms | +0% |
| ls (cached) | 89ms | 89ms | +0% |
| bin-paths (cached) | 94ms | 93ms | +1% |
| task-ls (cached) | 853ms | 843ms | +1% |
All callers now use parse_usage_spec_with_vars directly. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
### 🐛 Bug Fixes - **(exec)** respect PATH order for virtualenv resolution in mise x by @jdx in [#8342](#8342) - **(task)** revert process group changes that cause hangs with nested mise tasks by @jdx in [#8347](#8347) - **(task)** resolve vars from subdirectory configs for monorepo tasks by @jdx in [#8343](#8343) - **(task)** resolve dependencies before prepare to fix monorepo glob deps by @jdx in [#8353](#8353) - python noarch with Conda backend by @wolfv in [#8349](#8349) ### New Contributors - @wolfv made their first contribution in [#8349](#8349) ## 📦 Aqua Registry Updates #### New Packages (3) - [`alexhallam/tv`](https://github.com/alexhallam/tv) - [`arcanist-sh/hx`](https://github.com/arcanist-sh/hx) - [`dathere/qsv`](https://github.com/dathere/qsv) #### Updated Packages (3) - [`astral-sh/ruff`](https://github.com/astral-sh/ruff) - [`caarlos0/fork-cleaner`](https://github.com/caarlos0/fork-cleaner) - [`rhysd/actionlint`](https://github.com/rhysd/actionlint)
…dx#8343) ## Summary - Fix `[vars]` not being loaded from subdirectory configs when running monorepo tasks (e.g., `mise run //infra/stacks/gcp:greet`) - Resolve vars from the task's config hierarchy in `build_tera_context` and thread them through the script rendering chain via `TaskScriptParser.extra_vars` - Fix `parse_usage_spec_and_init_env` re-parsing scripts without vars, which caused rendering failures even when `render_run_scripts_with_args` had correct vars Closes jdx#6564 ## Test plan - [x] New e2e test `test_task_monorepo_vars` covers: root vars, subdirectory vars, inheritance, overriding, and MISE_ENV-specific vars - [x] Existing `test_task_monorepo_mise_env` still passes - [x] Existing `test_task_monorepo_tera_templates`, `test_task_monorepo_config_context`, `test_task_monorepo_usage_env` still pass - [x] All 481 unit tests pass - [x] Lint passes 🤖 Generated with [Claude Code](https://claude.com/claude-code) <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > Touches core task execution/rendering paths and changes how vars are injected into Tera contexts, which could affect template rendering for monorepo tasks; behavior is covered by a new end-to-end test. > > **Overview** > Monorepo tasks now resolve `[vars]` from the task’s subdirectory config hierarchy (and `mise.<env>.toml` overlays), merging them with root vars so subdir values can override while still inheriting unspecified root vars. > > This threads the resolved vars through task execution and script/usage parsing (`TaskContextBuilder` → `TaskExecutor` → `Task::parse_usage_spec_with_vars`/`render_run_scripts_with_args` → `TaskScriptParser`) to prevent re-parsing/rendering without the correct vars context. > > Adds an e2e test `test_task_monorepo_vars` covering root vs subdir vars, overrides/inheritance, and env-specific vars for monorepo task runs. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit 1f08f3e. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY --> --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
### 🐛 Bug Fixes - **(exec)** respect PATH order for virtualenv resolution in mise x by @jdx in [jdx#8342](jdx#8342) - **(task)** revert process group changes that cause hangs with nested mise tasks by @jdx in [jdx#8347](jdx#8347) - **(task)** resolve vars from subdirectory configs for monorepo tasks by @jdx in [jdx#8343](jdx#8343) - **(task)** resolve dependencies before prepare to fix monorepo glob deps by @jdx in [jdx#8353](jdx#8353) - python noarch with Conda backend by @wolfv in [jdx#8349](jdx#8349) ### New Contributors - @wolfv made their first contribution in [jdx#8349](jdx#8349) ## 📦 Aqua Registry Updates #### New Packages (3) - [`alexhallam/tv`](https://github.com/alexhallam/tv) - [`arcanist-sh/hx`](https://github.com/arcanist-sh/hx) - [`dathere/qsv`](https://github.com/dathere/qsv) #### Updated Packages (3) - [`astral-sh/ruff`](https://github.com/astral-sh/ruff) - [`caarlos0/fork-cleaner`](https://github.com/caarlos0/fork-cleaner) - [`rhysd/actionlint`](https://github.com/rhysd/actionlint)
Summary
[vars]not being loaded from subdirectory configs when running monorepo tasks (e.g.,mise run //infra/stacks/gcp:greet)build_tera_contextand thread them through the script rendering chain viaTaskScriptParser.extra_varsparse_usage_spec_and_init_envre-parsing scripts without vars, which caused rendering failures even whenrender_run_scripts_with_argshad correct varsCloses #6564
Test plan
test_task_monorepo_varscovers: root vars, subdirectory vars, inheritance, overriding, and MISE_ENV-specific varstest_task_monorepo_mise_envstill passestest_task_monorepo_tera_templates,test_task_monorepo_config_context,test_task_monorepo_usage_envstill pass🤖 Generated with Claude Code
Note
Medium Risk
Touches core task execution/rendering paths and changes how vars are injected into Tera contexts, which could affect template rendering for monorepo tasks; behavior is covered by a new end-to-end test.
Overview
Monorepo tasks now resolve
[vars]from the task’s subdirectory config hierarchy (andmise.<env>.tomloverlays), merging them with root vars so subdir values can override while still inheriting unspecified root vars.This threads the resolved vars through task execution and script/usage parsing (
TaskContextBuilder→TaskExecutor→Task::parse_usage_spec_with_vars/render_run_scripts_with_args→TaskScriptParser) to prevent re-parsing/rendering without the correct vars context.Adds an e2e test
test_task_monorepo_varscovering root vs subdir vars, overrides/inheritance, and env-specific vars for monorepo task runs.Written by Cursor Bugbot for commit 1f08f3e. This will update automatically on new commits. Configure here.