Skip to content

Commit

Permalink
fix: set env vars in task templates (#3758)
Browse files Browse the repository at this point in the history
* fix: set env vars in task templates

Fixes #3756

* [autofix.ci] apply automated fixes

* [autofix.ci] apply automated fixes (attempt 2/3)

---------

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
  • Loading branch information
jdx and autofix-ci[bot] authored Dec 21, 2024
1 parent c938977 commit dca96d2
Show file tree
Hide file tree
Showing 15 changed files with 189 additions and 100 deletions.
7 changes: 5 additions & 2 deletions docs/tasks/running-tasks.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,11 @@ See available tasks with `mise tasks`. To show tasks hidden with property `hide=

List dependencies of tasks with `mise task deps [tasks]...`.

Run a task with `mise task run`, `mise run`, or just `mise r`.
You might even want to make a shell alias like `alias mr='mise run --'` since this is likely a common command.
Run a task with `mise task run <task>`, `mise run <task>`, `mise r <task>`, or just `mise <task>`—however
that last one you should never put into scripts or documentation because if mise ever adds a command with that name in a
future mise version, the task will be shadowed and must be run with one of the other forms.

Most mise users will have an alias for `mise run` like `alias mr='mise run'`.

By default, tasks will execute with a maximum of 4 parallel jobs. Customize this with the `--jobs` option,
`jobs` setting or `MISE_JOBS` environment variable. The output normally will be by line, prefixed with the task
Expand Down
43 changes: 43 additions & 0 deletions e2e/env/test_env_template
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,46 @@ A = "a"
B = "{{ env.A }}"
EOF
assert "mise env -s bash | grep B" "export B=a"

cat <<EOF >mise.toml
[env]
FOO = "foo"
[tasks.foo]
env.BAR = "bar"
run = """
printf '\$FOO: %s\n' \$FOO
printf '\$BAR: %s\n' \$BAR
echo "{% raw %}{{ env.FOO }}{% endraw %}: {{ env.FOO }}"
echo "{% raw %}{{ env.BAR }}{% endraw %}: {{ env.BAR }}"
"""
EOF
assert "mise run --trace foo" "\$FOO: foo
\$BAR: bar
{{ env.FOO }}: foo
{{ env.BAR }}: bar"

cat <<EOF >mise.toml
[env]
FOO = "foo"
[tasks.foo]
env.BAR = "{{ env.FOO }}"
env.BAZ = "{{ env.BAR }}"
run = "printf '\$BAZ: %s\n' \$BAZ"
EOF
assert "mise run --trace foo" "\$BAZ: foo"

cat <<EOF >mise.toml
[env]
FOO = "/foo"
_.source = { path = "env.sh", tools = true }
_.path = "{{ env.FOO }}"
EOF
cat <<EOF >env.sh
#!/usr/bin/env bash
export BAR="\$PATH"
EOF
assert_contains "mise env -s bash | grep BAR" "export BAR='/foo:"
2 changes: 1 addition & 1 deletion src/backend/asdf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ impl AsdfBackend {
}
let script = sm.get_script_path(&ExecEnv);
let dir = dirs::CWD.clone().unwrap_or_default();
let ed = EnvDiff::from_bash_script(&script, &dir, &sm.env, Default::default())?;
let ed = EnvDiff::from_bash_script(&script, &dir, &sm.env, &Default::default())?;
let env = ed
.to_patches()
.into_iter()
Expand Down
8 changes: 5 additions & 3 deletions src/cli/generate/task_docs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,18 +40,20 @@ enum TaskDocsStyle {

impl TaskDocs {
pub fn run(self) -> eyre::Result<()> {
let config = Config::get();
let ts = config.get_toolset()?;
let dir = dirs::CWD.as_ref().unwrap();
let tasks = Config::get().load_tasks_in_dir(dir)?;
let tasks = config.load_tasks_in_dir(dir)?;
let mut out = vec![];
for task in tasks.iter().filter(|t| !t.hide) {
out.push(task.render_markdown(dir)?);
out.push(task.render_markdown(ts, dir)?);
}
if let Some(output) = &self.output {
if self.multi {
if output.is_dir() {
for (i, task) in tasks.iter().filter(|t| !t.hide).enumerate() {
let path = output.join(format!("{}.md", i));
file::write(&path, &task.render_markdown(dir)?)?;
file::write(&path, &task.render_markdown(ts, dir)?)?;
}
} else {
return Err(eyre::eyre!(
Expand Down
45 changes: 8 additions & 37 deletions src/cli/run.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use std::collections::{BTreeMap, HashSet};
use std::collections::BTreeMap;
use std::io::Write;
use std::iter::once;
use std::ops::Deref;
Expand All @@ -16,7 +16,7 @@ use crate::env_diff::EnvMap;
use crate::errors::Error;
use crate::file::display_path;
use crate::http::HTTP;
use crate::task::{Deps, EitherIntOrBool, GetMatchingExt, Task};
use crate::task::{Deps, GetMatchingExt, Task};
use crate::toolset::{InstallOptions, ToolsetBuilder};
use crate::ui::{ctrlc, prompt, style, time};
use crate::{dirs, env, exit, file, ui};
Expand All @@ -25,7 +25,6 @@ use console::Term;
use crossbeam_channel::{select, unbounded};
use demand::{DemandOption, Select};
use duct::IntoExecutablePath;
use either::Either;
use eyre::{bail, ensure, eyre, Result};
use glob::glob;
use itertools::Itertools;
Expand Down Expand Up @@ -338,7 +337,7 @@ impl Run {
tools.push(format!("{}@{}", k, v).parse()?);
}
let ts = ToolsetBuilder::new().with_args(&tools).build(&config)?;
let mut env = ts.env_with_path(&config)?;
let mut env = task.render_env(&ts)?;
let output = self.output(Some(task));
env.insert("MISE_TASK_OUTPUT".into(), output.to_string());
if output == TaskOutput::Prefix {
Expand Down Expand Up @@ -366,36 +365,14 @@ impl Run {
if let Some(config_root) = &task.config_root {
env.insert("MISE_CONFIG_ROOT".into(), config_root.display().to_string());
}
let string_env: Vec<(String, String)> = task
.env
.iter()
.filter_map(|(k, v)| match &v.0 {
Either::Left(v) => Some((k.to_string(), v.to_string())),
Either::Right(EitherIntOrBool(Either::Left(v))) => {
Some((k.to_string(), v.to_string()))
}
_ => None,
})
.collect_vec();
let rm_env = task
.env
.iter()
.filter(|(_, v)| v.0 == Either::Right(EitherIntOrBool(Either::Right(false))))
.map(|(k, _)| k)
.collect::<HashSet<_>>();
let env: EnvMap = env
.iter()
.map(|(k, v)| (k.to_string(), v.to_string()))
.chain(string_env)
.filter(|(k, _)| !rm_env.contains(k))
.collect();

let timer = std::time::Instant::now();

if let Some(file) = &task.file {
self.exec_file(file, task, &env, &prefix)?;
} else {
for (script, args) in task.render_run_scripts_with_args(self.cd.clone(), &task.args)? {
for (script, args) in
task.render_run_scripts_with_args(self.cd.clone(), &task.args, &env)?
{
self.exec_script(&script, &args, task, &env, &prefix)?;
}
}
Expand Down Expand Up @@ -505,18 +482,12 @@ impl Run {
}
}

fn exec_file(
&self,
file: &Path,
task: &Task,
env: &BTreeMap<String, String>,
prefix: &str,
) -> Result<()> {
fn exec_file(&self, file: &Path, task: &Task, env: &EnvMap, prefix: &str) -> Result<()> {
let config = Config::get();
let mut env = env.clone();
let command = file.to_string_lossy().to_string();
let args = task.args.iter().cloned().collect_vec();
let (spec, _) = task.parse_usage_spec(self.cd.clone())?;
let (spec, _) = task.parse_usage_spec(self.cd.clone(), &env)?;
if !spec.cmd.args.is_empty() || !spec.cmd.flags.is_empty() {
let args = once(command.clone()).chain(args.clone()).collect_vec();
let po = usage::parse(&spec, &args).map_err(|err| eyre!(err))?;
Expand Down
15 changes: 9 additions & 6 deletions src/cli/tasks/info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use itertools::Itertools;
use serde_json::json;

use crate::config::Config;
use crate::env_diff::EnvMap;
use crate::file::display_path;
use crate::task::Task;
use crate::ui::info;
Expand All @@ -25,10 +26,12 @@ impl TasksInfo {
let task = config.tasks()?.get(&self.task);

if let Some(task) = task {
let ts = config.get_toolset()?;
let env = task.render_env(ts)?;
if self.json {
self.display_json(task)?;
self.display_json(task, &env)?;
} else {
self.display(task)?;
self.display(task, &env)?;
}
} else {
bail!(
Expand All @@ -40,7 +43,7 @@ impl TasksInfo {
Ok(())
}

fn display(&self, task: &Task) -> Result<()> {
fn display(&self, task: &Task, env: &EnvMap) -> Result<()> {
info::inline_section("Task", &task.name)?;
if !task.aliases.is_empty() {
info::inline_section("Aliases", task.aliases.join(", "))?;
Expand Down Expand Up @@ -82,15 +85,15 @@ impl TasksInfo {
if !task.env.is_empty() {
info::section("Environment Variables", toml::to_string_pretty(&task.env)?)?;
}
let (spec, _) = task.parse_usage_spec(None)?;
let (spec, _) = task.parse_usage_spec(None, env)?;
if !spec.is_empty() {
info::section("Usage Spec", &spec)?;
}
Ok(())
}

fn display_json(&self, task: &Task) -> Result<()> {
let (spec, _) = task.parse_usage_spec(None)?;
fn display_json(&self, task: &Task, env: &EnvMap) -> Result<()> {
let (spec, _) = task.parse_usage_spec(None, env)?;
let o = json!({
"name": task.name.to_string(),
"aliases": task.aliases.join(", "),
Expand Down
17 changes: 10 additions & 7 deletions src/cli/tasks/ls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use itertools::Itertools;
use crate::config::Config;
use crate::file::{display_path, display_rel_path};
use crate::task::Task;
use crate::toolset::Toolset;
use crate::ui::table::MiseTable;

/// List available tasks to execute
Expand Down Expand Up @@ -62,6 +63,7 @@ pub enum SortOrder {
impl TasksLs {
pub fn run(self) -> Result<()> {
let config = Config::try_get()?;
let ts = config.get_toolset()?;
let tasks = config
.tasks()?
.values()
Expand All @@ -71,16 +73,16 @@ impl TasksLs {
.collect::<Vec<Task>>();

if self.usage {
self.display_usage(tasks)?;
self.display_usage(ts, tasks)?;
} else if self.json {
self.display_json(tasks)?;
self.display_json(ts, tasks)?;
} else {
self.display(tasks)?;
self.display(ts, tasks)?;
}
Ok(())
}

fn display(&self, tasks: Vec<Task>) -> Result<()> {
fn display(&self, _ts: &Toolset, tasks: Vec<Task>) -> Result<()> {
let mut table = MiseTable::new(
self.no_header,
if self.extended {
Expand All @@ -95,10 +97,11 @@ impl TasksLs {
table.print()
}

fn display_usage(&self, tasks: Vec<Task>) -> Result<()> {
fn display_usage(&self, ts: &Toolset, tasks: Vec<Task>) -> Result<()> {
let mut usage = usage::Spec::default();
for task in tasks {
let (mut task_spec, _) = task.parse_usage_spec(None)?;
let env = task.render_env(ts)?;
let (mut task_spec, _) = task.parse_usage_spec(None, &env)?;
for (name, complete) in task_spec.complete {
task_spec.cmd.complete.insert(name, complete);
}
Expand All @@ -111,7 +114,7 @@ impl TasksLs {
Ok(())
}

fn display_json(&self, tasks: Vec<Task>) -> Result<()> {
fn display_json(&self, _ts: &Toolset, tasks: Vec<Task>) -> Result<()> {
let array_items = tasks
.into_iter()
.filter(|t| self.hidden || !t.hide)
Expand Down
8 changes: 7 additions & 1 deletion src/config/env_directive/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use crate::dirs;
use crate::env;
use crate::env_diff::EnvMap;
use crate::file::display_path;
use crate::path_env::PathEnv;
use crate::tera::{get_tera, tera_exec};
use eyre::{eyre, Context};
use indexmap::IndexMap;
Expand Down Expand Up @@ -224,7 +225,12 @@ impl EnvResults {
r.env_remove.insert(k);
}
EnvDirective::Path(input_str, _opts) => {
Self::path(&mut ctx, &mut tera, &mut r, &mut paths, source, input_str)?;
let path = Self::path(&mut ctx, &mut tera, &mut r, &source, input_str)?;
paths.push((path.clone(), source.clone()));
let env_path = env.get(&*env::PATH_KEY).cloned().unwrap_or_default().0;
let mut env_path: PathEnv = env_path.parse()?;
env_path.add(path);
env.insert(env::PATH_KEY.to_string(), (env_path.to_string(), None));
}
EnvDirective::File(input, _opts) => {
let files = Self::file(
Expand Down
19 changes: 5 additions & 14 deletions src/config/env_directive/path.rs
Original file line number Diff line number Diff line change
@@ -1,26 +1,17 @@
use crate::config::env_directive::EnvResults;
use crate::result;
use std::path::PathBuf;
use std::path::{Path, PathBuf};

impl EnvResults {
pub fn path(
ctx: &mut tera::Context,
tera: &mut tera::Tera,
r: &mut EnvResults,
paths: &mut Vec<(PathBuf, PathBuf)>,
source: PathBuf,
source: &Path,
input: String,
) -> result::Result<()> {
// trace!("resolve: input_str: {:#?}", input_str);
// trace!(
// "resolve: normal: input: {:?}, input.to_string(): {:?}",
// &input,
// input.to_string_lossy().as_ref()
// );
let s = r.parse_template(ctx, tera, &source, &input)?;
// trace!("resolve: s: {:?}", &s);
paths.push((s.into(), source));
Ok(())
) -> result::Result<PathBuf> {
r.parse_template(ctx, tera, source, &input)
.map(PathBuf::from)
}
}

Expand Down
12 changes: 7 additions & 5 deletions src/config/env_directive/source.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,16 @@ impl EnvResults {
) -> Result<IndexMap<PathBuf, IndexMap<String, String>>> {
let mut out = IndexMap::new();
let s = r.parse_template(ctx, tera, source, &input)?;
let orig_path = env_vars.get(&*env::PATH_KEY).cloned().unwrap_or_default();
let mut env_diff_opts = EnvDiffOptions::default();
env_diff_opts.ignore_keys.shift_remove(&*env::PATH_KEY); // allow modifying PATH
for p in xx::file::glob(normalize_path(config_root, s.into())).unwrap_or_default() {
if !p.exists() {
continue;
}
let env = out.entry(p.clone()).or_insert_with(IndexMap::new);
let orig_path = env_vars.get(&*env::PATH_KEY).cloned().unwrap_or_default();
let mut env_diff_opts = EnvDiffOptions::default();
env_diff_opts.ignore_keys.shift_remove(&*env::PATH_KEY); // allow modifying PATH
let env_diff =
EnvDiff::from_bash_script(&p, config_root, env_vars.clone(), env_diff_opts)
.unwrap_or_default();
EnvDiff::from_bash_script(&p, config_root, env_vars.clone(), &env_diff_opts)?;
for p in env_diff.to_patches() {
match p {
EnvDiffOperation::Add(k, v) | EnvDiffOperation::Change(k, v) => {
Expand Down
Loading

0 comments on commit dca96d2

Please sign in to comment.