Skip to content

Commit

Permalink
feat(turbo): add platform env support
Browse files Browse the repository at this point in the history
  • Loading branch information
tknickman committed Sep 6, 2024
1 parent c84638a commit 8bc0d6b
Show file tree
Hide file tree
Showing 5 changed files with 107 additions and 1 deletion.
2 changes: 2 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions crates/turborepo-env/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ regex = { workspace = true }
serde = { workspace = true }
sha2 = { workspace = true }
thiserror = { workspace = true }
turborepo-ci = { workspace = true }
turborepo-ui = { workspace = true }

[dev-dependencies]
test-case = { workspace = true }
90 changes: 90 additions & 0 deletions crates/turborepo-env/src/ci.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
use turborepo_ci::Vendor;
use turborepo_ui::{cprint, cprintln, ColorConfig, GREY, UNDERLINE, YELLOW};

use crate::EnvironmentVariableMap;

pub struct CIEnv {
ci_keys: Vec<String>,
}

const SYSTEM_ENV_KEY: &str = "TURBO_SYSTEM_ENV";
const VALIDATE_PLATFORM_ENV: &str = "TURBO_VALIDATE_PLATFORM_ENV";

impl CIEnv {
pub fn new() -> Self {

Check failure on line 14 in crates/turborepo-env/src/ci.rs

View workflow job for this annotation

GitHub Actions / Rust lints

you should consider adding a `Default` implementation for `CIEnv`
let ci_keys = std::env::var(SYSTEM_ENV_KEY)
.unwrap_or_default()
.split(',')
.map(|s| s.to_string())
.collect();

Self { ci_keys }
}

pub fn enabled() -> bool {
let validate_platform_env = std::env::var(VALIDATE_PLATFORM_ENV).unwrap_or_default();
validate_platform_env == "1" || validate_platform_env == "true"
}

pub fn validate(
&self,
execution_env: &EnvironmentVariableMap,
color_config: ColorConfig,
task_id_for_display: &str,
) {
if !Self::enabled() {
return;
}

let missing_env = self.diff(execution_env);
if !missing_env.is_empty() {
self.output(missing_env, task_id_for_display, color_config);
}
}

pub fn diff(&self, execution_env: &EnvironmentVariableMap) -> Vec<String> {
self.ci_keys
.iter()
.filter(|key| !execution_env.contains_key(*key))
.map(|s| s.to_string())
.collect()
}

pub fn output(
&self,
missing: Vec<String>,
task_id_for_display: &str,
color_config: ColorConfig,
) {
let ci = Vendor::get_constant().unwrap_or("unknown");
match ci {
"VERCEL" => {
cprintln!(color_config, YELLOW, "\n{} WARNINGS:", task_id_for_display);
cprintln!(
color_config,
GREY,
"1. The following environment variables are set on your Vercel project, but \
missing from \"turbo.json\""
);
for key in missing {
cprint!(color_config, GREY, " - ");
cprint!(color_config, UNDERLINE, "{}\n", key);
}
println!();
}
_ => {
cprintln!(color_config, YELLOW, "\n{} WARNINGS:", task_id_for_display);
cprintln!(
color_config,
GREY,
"1. The following environment variables are missing from \"turbo.json\""
);
for key in missing {
cprint!(color_config, GREY, " - ");
cprint!(color_config, UNDERLINE, "{}\n", key);
}
println!();
}
}
}
}
2 changes: 2 additions & 0 deletions crates/turborepo-env/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ use serde::Serialize;
use sha2::{Digest, Sha256};
use thiserror::Error;

pub mod ci;

const DEFAULT_ENV_VARS: [&str; 1] = ["VERCEL_ANALYTICS_ID"];

#[derive(Clone, Debug, Error)]
Expand Down
12 changes: 11 additions & 1 deletion crates/turborepo-lib/src/task_graph/visitor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ use tokio::sync::{mpsc, oneshot};
use tracing::{debug, error, Instrument, Span};
use turbopath::{AbsoluteSystemPath, AbsoluteSystemPathBuf, AnchoredSystemPath};
use turborepo_ci::{Vendor, VendorBehavior};
use turborepo_env::EnvironmentVariableMap;
use turborepo_env::{ci::CIEnv, EnvironmentVariableMap};
use turborepo_repository::{
package_graph::{PackageGraph, PackageName, ROOT_PKG_NAME},
package_manager::PackageManager,
Expand Down Expand Up @@ -294,6 +294,7 @@ impl<'a> Visitor<'a> {
} else {
TaskOutput::Direct(self.output_client(&info, vendor_behavior))
};

let tracker = self.run_tracker.track_task(info.clone().into_owned());
let spaces_client = self.run_tracker.spaces_task_client();
let parent_span = Span::current();
Expand Down Expand Up @@ -694,6 +695,7 @@ impl<'a> ExecContextFactory<'a> {
errors: self.errors.clone(),
takes_input,
task_access,
ci_env: CIEnv::new(),
}
}

Expand Down Expand Up @@ -730,6 +732,7 @@ struct ExecContext {
errors: Arc<Mutex<Vec<TaskError>>>,
takes_input: bool,
task_access: TaskAccess,
ci_env: CIEnv,
}

enum ExecOutcome {
Expand Down Expand Up @@ -882,6 +885,13 @@ impl ExecContext {
}
}

// validate the provided environment variables against those in CI
self.ci_env.validate(
&self.execution_env,
self.color_config,
self.task_id_for_display.as_str(),
);

match self
.task_cache
.restore_outputs(&mut prefixed_ui, telemetry)
Expand Down

0 comments on commit 8bc0d6b

Please sign in to comment.