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

refactor: add spans to some turbo.json fields #10627

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 5 commits into from
Jul 3, 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
10 changes: 6 additions & 4 deletions crates/turborepo-lib/src/config/turbo_json.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,14 @@ impl<'a> TurboJsonReader<'a> {

// Don't allow token to be set for shared config.
opts.token = None;
opts.ui = turbo_json.ui;
opts.allow_no_package_manager = turbo_json.allow_no_package_manager;
opts.ui = turbo_json.ui.map(|ui| *ui.as_inner());
opts.allow_no_package_manager = turbo_json
.allow_no_package_manager
.map(|allow| *allow.as_inner());
opts.daemon = turbo_json.daemon.map(|daemon| *daemon.as_inner());
opts.env_mode = turbo_json.env_mode;
opts.env_mode = turbo_json.env_mode.map(|mode| *mode.as_inner());
opts.cache_dir = cache_dir;
opts.concurrency = turbo_json.concurrency;
opts.concurrency = turbo_json.concurrency.map(|c| c.as_inner().clone());
Ok(opts)
}
}
Expand Down
4 changes: 2 additions & 2 deletions crates/turborepo-lib/src/turbo_json/loader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -372,7 +372,7 @@ fn root_turbo_json_from_scripts(scripts: &[String]) -> Result<TurboJson, Error>
task_name,
Spanned::new(RawTaskDefinition {
cache: Some(Spanned::new(false)),
env_mode: Some(EnvMode::Loose),
env_mode: Some(Spanned::new(EnvMode::Loose)),
..Default::default()
}),
);
Expand All @@ -391,7 +391,7 @@ fn workspace_turbo_json_from_scripts(scripts: &[String]) -> Result<TurboJson, Er
task_name,
Spanned::new(RawTaskDefinition {
cache: Some(Spanned::new(false)),
env_mode: Some(EnvMode::Loose),
env_mode: Some(Spanned::new(EnvMode::Loose)),
..Default::default()
}),
);
Expand Down
76 changes: 48 additions & 28 deletions crates/turborepo-lib/src/turbo_json/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,37 +70,52 @@ pub struct TurboJson {
#[serde(rename_all = "camelCase")]
pub(crate) struct RawRemoteCacheOptions {
#[serde(skip_serializing_if = "Option::is_none")]
api_url: Option<String>,
api_url: Option<Spanned<String>>,
#[serde(skip_serializing_if = "Option::is_none")]
login_url: Option<String>,
login_url: Option<Spanned<String>>,
#[serde(skip_serializing_if = "Option::is_none")]
team_slug: Option<String>,
team_slug: Option<Spanned<String>>,
#[serde(skip_serializing_if = "Option::is_none")]
team_id: Option<String>,
team_id: Option<Spanned<String>>,
#[serde(skip_serializing_if = "Option::is_none")]
signature: Option<bool>,
signature: Option<Spanned<bool>>,
#[serde(skip_serializing_if = "Option::is_none")]
preflight: Option<bool>,
preflight: Option<Spanned<bool>>,
#[serde(skip_serializing_if = "Option::is_none")]
timeout: Option<u64>,
timeout: Option<Spanned<u64>>,
#[serde(skip_serializing_if = "Option::is_none")]
enabled: Option<bool>,
enabled: Option<Spanned<bool>>,
#[serde(skip_serializing_if = "Option::is_none")]
upload_timeout: Option<u64>,
upload_timeout: Option<Spanned<u64>>,
}

impl From<&RawRemoteCacheOptions> for ConfigurationOptions {
fn from(remote_cache_opts: &RawRemoteCacheOptions) -> Self {
Self {
api_url: remote_cache_opts.api_url.clone(),
login_url: remote_cache_opts.login_url.clone(),
team_slug: remote_cache_opts.team_slug.clone(),
team_id: remote_cache_opts.team_id.clone(),
signature: remote_cache_opts.signature,
preflight: remote_cache_opts.preflight,
timeout: remote_cache_opts.timeout,
upload_timeout: remote_cache_opts.upload_timeout,
enabled: remote_cache_opts.enabled,
api_url: remote_cache_opts
.api_url
.as_ref()
.map(|s| s.as_inner().clone()),
login_url: remote_cache_opts
.login_url
.as_ref()
.map(|s| s.as_inner().clone()),
team_slug: remote_cache_opts
.team_slug
.as_ref()
.map(|s| s.as_inner().clone()),
team_id: remote_cache_opts
.team_id
.as_ref()
.map(|s| s.as_inner().clone()),
signature: remote_cache_opts.signature.as_ref().map(|s| *s.as_inner()),
preflight: remote_cache_opts.preflight.as_ref().map(|s| *s.as_inner()),
timeout: remote_cache_opts.timeout.as_ref().map(|s| *s.as_inner()),
upload_timeout: remote_cache_opts
.upload_timeout
.as_ref()
.map(|s| *s.as_inner()),
enabled: remote_cache_opts.enabled.as_ref().map(|s| *s.as_inner()),
..Self::default()
}
}
Expand Down Expand Up @@ -139,21 +154,21 @@ pub struct RawTurboJson {
#[serde(skip_serializing_if = "Option::is_none")]
pub(crate) remote_cache: Option<RawRemoteCacheOptions>,
#[serde(skip_serializing_if = "Option::is_none", rename = "ui")]
pub ui: Option<UIMode>,
pub ui: Option<Spanned<UIMode>>,
#[serde(
skip_serializing_if = "Option::is_none",
rename = "dangerouslyDisablePackageManagerCheck"
)]
pub allow_no_package_manager: Option<bool>,
pub allow_no_package_manager: Option<Spanned<bool>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub daemon: Option<Spanned<bool>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub env_mode: Option<EnvMode>,
pub env_mode: Option<Spanned<EnvMode>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub cache_dir: Option<Spanned<UnescapedString>>,

#[serde(skip_serializing_if = "Option::is_none")]
pub no_update_notifier: Option<bool>,
pub no_update_notifier: Option<Spanned<bool>>,

#[serde(skip_serializing_if = "Option::is_none")]
pub tags: Option<Spanned<Vec<Spanned<String>>>>,
Expand All @@ -162,7 +177,7 @@ pub struct RawTurboJson {
pub boundaries: Option<Spanned<BoundariesConfig>>,

#[serde(skip_serializing_if = "Option::is_none")]
pub concurrency: Option<String>,
pub concurrency: Option<Spanned<String>>,

#[serde(skip_serializing_if = "Option::is_none")]
pub future_flags: Option<Spanned<FutureFlags>>,
Expand Down Expand Up @@ -270,7 +285,7 @@ pub struct RawTaskDefinition {
// TODO: Remove this once we have the ability to load task definitions directly
// instead of deriving them from a TurboJson
#[serde(skip)]
env_mode: Option<EnvMode>,
env_mode: Option<Spanned<EnvMode>>,
// This can currently only be set internally and isn't a part of turbo.json
#[serde(skip_serializing_if = "Option::is_none")]
with: Option<Vec<Spanned<UnescapedString>>>,
Expand Down Expand Up @@ -478,7 +493,7 @@ impl TaskDefinition {
persistent,
interruptible: *interruptible,
interactive,
env_mode: raw_task.env_mode,
env_mode: raw_task.env_mode.map(|mode| *mode.as_inner()),
with,
})
}
Expand Down Expand Up @@ -701,7 +716,7 @@ impl TurboJson {
)))])
}),
persistent: Some(Spanned::new(true)),
env_mode: Some(EnvMode::Loose),
env_mode: Some(Spanned::new(EnvMode::Loose)),
..Default::default()
}),
);
Expand Down Expand Up @@ -1243,7 +1258,7 @@ mod tests {
#[test_case(r#"{}"#, None ; "missing")]
fn test_ui(json: &str, expected: Option<UIMode>) {
let json = RawTurboJson::parse(json, "").unwrap();
assert_eq!(json.ui, expected);
assert_eq!(json.ui.as_ref().map(|ui| *ui.as_inner()), expected);
}

#[test_case(r#"{ "experimentalSpaces": { "id": "hello-world" } }"#, Some(SpacesJson { id: Some("hello-world".to_string().into()) }))]
Expand Down Expand Up @@ -1275,7 +1290,12 @@ mod tests {
#[test_case(r#"{}"#, None ; "missing")]
fn test_allow_no_package_manager_serde(json_str: &str, expected: Option<bool>) {
let json = RawTurboJson::parse(json_str, "").unwrap();
assert_eq!(json.allow_no_package_manager, expected);
assert_eq!(
json.allow_no_package_manager
.as_ref()
.map(|allow| *allow.as_inner()),
expected
);
let serialized = serde_json::to_string(&json).unwrap();
assert_eq!(serialized, json_str);
}
Expand Down
48 changes: 45 additions & 3 deletions crates/turborepo-lib/src/turbo_json/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ use turborepo_unescape::UnescapedString;
use crate::{
boundaries::{BoundariesConfig, Permissions, Rule},
run::task_id::TaskName,
turbo_json::{Pipeline, RawTaskDefinition, RawTurboJson, Spanned},
turbo_json::{Pipeline, RawRemoteCacheOptions, RawTaskDefinition, RawTurboJson, Spanned},
};

#[derive(Debug, Error, Diagnostic)]
Expand Down Expand Up @@ -116,7 +116,15 @@ impl WithMetadata for RawTurboJson {

self.tasks.add_text(text.clone());
self.cache_dir.add_text(text.clone());
self.pipeline.add_text(text);
self.pipeline.add_text(text.clone());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Might be able to skip pipeline

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm thinking I'm going to leave it for the sake of consistency - unless there's some perf or other upside I'm not realizing. The consternation I experienced when I went to work with these and some had spans and some didn't... :old-man-yells-at-unexpected-things:

self.remote_cache.add_text(text.clone());
self.ui.add_text(text.clone());
self.allow_no_package_manager.add_text(text.clone());
self.daemon.add_text(text.clone());
self.env_mode.add_text(text.clone());
self.no_update_notifier.add_text(text.clone());
self.concurrency.add_text(text.clone());
self.future_flags.add_text(text);
}

fn add_path(&mut self, path: Arc<str>) {
Expand All @@ -135,7 +143,15 @@ impl WithMetadata for RawTurboJson {
}
self.tasks.add_path(path.clone());
self.cache_dir.add_path(path.clone());
self.pipeline.add_path(path);
self.pipeline.add_path(path.clone());
self.remote_cache.add_path(path.clone());
self.ui.add_path(path.clone());
self.allow_no_package_manager.add_path(path.clone());
self.daemon.add_path(path.clone());
self.env_mode.add_path(path.clone());
self.no_update_notifier.add_path(path.clone());
self.concurrency.add_path(path.clone());
self.future_flags.add_path(path);
}
}

Expand Down Expand Up @@ -275,6 +291,32 @@ impl WithMetadata for RawTaskDefinition {
}
}

impl WithMetadata for RawRemoteCacheOptions {
fn add_text(&mut self, text: Arc<str>) {
self.api_url.add_text(text.clone());
self.login_url.add_text(text.clone());
self.team_slug.add_text(text.clone());
self.team_id.add_text(text.clone());
self.signature.add_text(text.clone());
self.preflight.add_text(text.clone());
self.timeout.add_text(text.clone());
self.enabled.add_text(text.clone());
self.upload_timeout.add_text(text);
}

fn add_path(&mut self, path: Arc<str>) {
self.api_url.add_path(path.clone());
self.login_url.add_path(path.clone());
self.team_slug.add_path(path.clone());
self.team_id.add_path(path.clone());
self.signature.add_path(path.clone());
self.preflight.add_path(path.clone());
self.timeout.add_path(path.clone());
self.enabled.add_path(path.clone());
self.upload_timeout.add_path(path);
}
}

impl RawTurboJson {
// A simple helper for tests
#[cfg(test)]
Expand Down
Loading