Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 69 additions & 0 deletions e2e/tasks/test_task_monorepo_vars
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
#!/usr/bin/env bash
# Test that monorepo tasks properly load [vars] from subdirectory configs
export MISE_EXPERIMENTAL=1

# Create monorepo root config with vars
cat <<EOF >mise.toml
experimental_monorepo_root = true

[monorepo]
config_roots = ["infra/stacks/*"]

[vars]
ROOT_VAR = "root_value"
SHARED_VAR = "from_root"

[tasks.root-greet]
run = 'echo "ROOT_VAR={{vars.ROOT_VAR}} SHARED_VAR={{vars.SHARED_VAR}}"'
EOF

# Create subdirectory config with its own vars and tasks
mkdir -p infra/stacks/gcp
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

# Create MISE_ENV-specific config for the subdirectory
cat <<EOF >infra/stacks/gcp/mise.dev.toml
[vars]
DEV_VAR = "dev_value"
SHARED_VAR = "from_gcp_dev"
EOF

# Test 1: Root task sees root vars
echo "=== Test 1: Root task sees root vars ==="
unset MISE_ENV
output=$(mise run //:root-greet)
echo "$output"
assert_contains "echo '$output'" "ROOT_VAR=root_value"
assert_contains "echo '$output'" "SHARED_VAR=from_root"

# Test 2: Subdirectory task sees its own vars, inherits root vars, and overrides shared vars
echo "=== Test 2: Subdirectory task var resolution ==="
unset MISE_ENV
output=$(mise run '//infra/stacks/gcp:greet')
echo "$output"
# Core bug fix: subdirectory vars are loaded
assert_contains "echo '$output'" "GCP_VAR=gcp_value"
# Subdirectory vars override root vars of the same name
assert_contains "echo '$output'" "SHARED_VAR=from_gcp"
# Subdirectory task still inherits root vars it doesn't override
assert_contains "echo '$output'" "ROOT_VAR=root_value"

# Test 3: Subdirectory task with MISE_ENV sees env-specific vars
echo "=== Test 3: MISE_ENV-specific vars in subdirectory ==="
output=$(MISE_ENV=dev mise run '//infra/stacks/gcp:greet-dev')
echo "$output"
assert_contains "echo '$output'" "DEV_VAR=dev_value"
# MISE_ENV vars should override base vars
assert_contains "echo '$output'" "SHARED_VAR=from_gcp_dev"

echo "=== All tests passed! ==="
31 changes: 28 additions & 3 deletions src/task/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -691,6 +691,17 @@ impl Task {
config: &Arc<Config>,
cwd: Option<PathBuf>,
env: &EnvMap,
) -> Result<(usage::Spec, Vec<String>)> {
self.parse_usage_spec_with_vars(config, cwd, env, None)
.await
}
Comment thread
cursor[bot] marked this conversation as resolved.
Outdated

pub async fn parse_usage_spec_with_vars(
&self,
config: &Arc<Config>,
cwd: Option<PathBuf>,
env: &EnvMap,
extra_vars: Option<IndexMap<String, String>>,
) -> Result<(usage::Spec, Vec<String>)> {
let (mut spec, scripts) = if let Some(file) = self.file_path(config).await? {
let spec = usage::Spec::parse_script(&file)
Expand All @@ -704,7 +715,7 @@ impl Task {
(spec, vec![])
} else {
let scripts_only = self.run_script_strings();
let (scripts, spec) = TaskScriptParser::new(cwd)
let (scripts, spec) = Self::make_script_parser(cwd, extra_vars)
.parse_run_scripts(config, self, &scripts_only, env)
.await?;
(spec, scripts)
Expand All @@ -713,6 +724,17 @@ impl Task {
Ok((spec, scripts))
}

fn make_script_parser(
cwd: Option<PathBuf>,
extra_vars: Option<IndexMap<String, String>>,
) -> TaskScriptParser {
let parser = TaskScriptParser::new(cwd);
match extra_vars {
Some(vars) => parser.with_extra_vars(vars),
None => parser,
}
}

/// Parse usage spec for display purposes without expensive environment rendering
pub async fn parse_usage_spec_for_display(&self, config: &Arc<Config>) -> Result<usage::Spec> {
let dir = self.dir(config).await?;
Expand Down Expand Up @@ -741,11 +763,14 @@ impl Task {
cwd: Option<PathBuf>,
args: &[String],
env: &EnvMap,
extra_vars: Option<IndexMap<String, String>>,
) -> Result<Vec<(String, Vec<String>)>> {
let (spec, scripts) = self.parse_usage_spec(config, cwd.clone(), env).await?;
let (spec, scripts) = self
.parse_usage_spec_with_vars(config, cwd.clone(), env, extra_vars.clone())
.await?;
if has_any_args_defined(&spec) {
let scripts_only = self.run_script_strings();
let scripts = TaskScriptParser::new(cwd)
let scripts = Self::make_script_parser(cwd, extra_vars)
.parse_run_scripts_with_args(config, self, &scripts_only, env, args, &spec)
.await?;
Ok(scripts.into_iter().map(|s| (s, vec![])).collect())
Expand Down
Loading
Loading