这是indexloc提供的服务,不要输入任何密码
Skip to content

fix(env): allow passThroughEnv to negate built ins and globalPassThroughEnv #9680

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
Jan 17, 2025
Merged
Show file tree
Hide file tree
Changes from all 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
110 changes: 109 additions & 1 deletion crates/turborepo-env/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,7 @@ impl EnvironmentVariableMap {
// that user exclusions have primacy over inferred inclusions.
pub fn wildcard_map_from_wildcards_unresolved(
&self,
wildcard_patterns: &[String],
wildcard_patterns: &[impl AsRef<str>],
) -> Result<WildcardMaps, Error> {
if wildcard_patterns.is_empty() {
return Ok(WildcardMaps {
Expand All @@ -229,6 +229,60 @@ impl EnvironmentVariableMap {

self.wildcard_map_from_wildcards(wildcard_patterns)
}

/// Return a detailed map for which environment variables are factored into
/// the task's hash
pub fn hashable_task_env(
&self,
computed_wildcards: &[String],
task_env: &[String],
) -> Result<DetailedMap, Error> {
let mut explicit_env_var_map = EnvironmentVariableMap::default();
let mut all_env_var_map = EnvironmentVariableMap::default();
let mut matching_env_var_map = EnvironmentVariableMap::default();
let inference_env_var_map = self.from_wildcards(computed_wildcards)?;

let user_env_var_set = self.wildcard_map_from_wildcards_unresolved(task_env)?;

all_env_var_map.union(&user_env_var_set.inclusions);
all_env_var_map.union(&inference_env_var_map);
all_env_var_map.difference(&user_env_var_set.exclusions);

explicit_env_var_map.union(&user_env_var_set.inclusions);
explicit_env_var_map.difference(&user_env_var_set.exclusions);

matching_env_var_map.union(&inference_env_var_map);
matching_env_var_map.difference(&user_env_var_set.exclusions);

Ok(DetailedMap {
all: all_env_var_map,
by_source: BySource {
explicit: explicit_env_var_map,
matching: matching_env_var_map,
},
})
}

/// Constructs an environment map that contains pass through environment
/// variables
pub fn pass_through_env(
&self,
builtins: &[&str],
global_env: &Self,
task_pass_through: &[impl AsRef<str>],
) -> Result<Self, Error> {
let mut pass_through_env = EnvironmentVariableMap::default();
let default_env_var_pass_through_map = self.from_wildcards(builtins)?;
let task_pass_through_env =
self.wildcard_map_from_wildcards_unresolved(task_pass_through)?;

pass_through_env.union(&default_env_var_pass_through_map);
pass_through_env.union(global_env);
pass_through_env.union(&task_pass_through_env.inclusions);
pass_through_env.difference(&task_pass_through_env.exclusions);

Ok(pass_through_env)
}
}

const WILDCARD: char = '*';
Expand Down Expand Up @@ -358,4 +412,58 @@ mod tests {
actual.sort();
assert_eq!(actual, expected);
}

#[test_case(&["FOO*"], &["BAR"], &["BAR", "FOO", "FOOBAR", "FOOD"] ; "wildcard")]
#[test_case(&["FOO*", "!FOOBAR"], &["BAR"], &["BAR", "FOO", "FOOD"] ; "omit wild")]
#[test_case(&["FOO*"], &["!FOOBAR"], &["FOO", "FOOD"] ; "omit task")]
fn test_hashable_env(wildcards: &[&str], task: &[&str], expected: &[&str]) {
let env_at_start = EnvironmentVariableMap(
vec![
("FOO", "bar"),
("FOOBAR", "baz"),
("FOOD", "cheese"),
("BAR", "nuts"),
]
.into_iter()
.map(|(k, v)| (k.to_owned(), v.to_owned()))
.collect(),
);
let wildcards: Vec<_> = wildcards.iter().map(|s| s.to_string()).collect();
let task: Vec<_> = task.iter().map(|s| s.to_string()).collect();
let output = env_at_start.hashable_task_env(&wildcards, &task).unwrap();
let mut actual: Vec<_> = output.all.keys().map(|s| s.as_str()).collect();
actual.sort();
assert_eq!(actual, expected);
}

#[test_case(&["FOO*"], &["FOO", "FOOBAR", "FOOD", "PATH"] ; "folds 3 sources")]
#[test_case(&["!FOO"], &["PATH"] ; "remove global")]
#[test_case(&["!PATH"], &["FOO"] ; "remove builtin")]
#[test_case(&["FOO*", "!FOOD"], &["FOO", "FOOBAR", "PATH"] ; "mixing negations")]
fn test_pass_through_env(task: &[&str], expected: &[&str]) {
let env_at_start = EnvironmentVariableMap(
vec![
("PATH", "of"),
("FOO", "bar"),
("FOOBAR", "baz"),
("FOOD", "cheese"),
("BAR", "nuts"),
]
.into_iter()
.map(|(k, v)| (k.to_owned(), v.to_owned()))
.collect(),
);
let global_env = EnvironmentVariableMap(
vec![("FOO", "bar")]
.into_iter()
.map(|(k, v)| (k.to_owned(), v.to_owned()))
.collect(),
);
let output = env_at_start
.pass_through_env(&["PATH"], &global_env, task)
.unwrap();
let mut actual: Vec<_> = output.keys().map(|s| s.as_str()).collect();
actual.sort();
assert_eq!(actual, expected);
}
}
9 changes: 4 additions & 5 deletions crates/turborepo-lib/src/task_graph/visitor/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,6 @@ use crate::{
pub struct Visitor<'a> {
color_cache: ColorSelector,
dry: bool,
global_env: EnvironmentVariableMap,
global_env_mode: EnvMode,
manager: ProcessManager,
run_opts: &'a RunOpts,
Expand Down Expand Up @@ -146,6 +145,7 @@ impl<'a> Visitor<'a> {
run_opts,
env_at_execution_start,
global_hash,
global_env,
);

let sink = Self::sink(run_opts);
Expand All @@ -172,7 +172,6 @@ impl<'a> Visitor<'a> {
sink,
task_hasher,
color_config,
global_env,
ui_sender,
is_watch,
warnings: Default::default(),
Expand Down Expand Up @@ -259,9 +258,9 @@ impl<'a> Visitor<'a> {
// We do this calculation earlier than we do in Go due to the `task_hasher`
// being !Send. In the future we can look at doing this right before
// task execution instead.
let execution_env =
self.task_hasher
.env(&info, task_env_mode, task_definition, &self.global_env)?;
let execution_env = self
.task_hasher
.env(&info, task_env_mode, task_definition)?;

let task_cache = self.run_cache.task_cache(
task_definition,
Expand Down
Loading
Loading