这是indexloc提供的服务,不要输入任何密码
Skip to content
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
1 change: 1 addition & 0 deletions Cargo.lock

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

1 change: 1 addition & 0 deletions crates/turborepo-lib/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ daemon-file-hashing = []
anyhow = { workspace = true, features = ["backtrace"] }
assert_cmd = { workspace = true }
async-stream = "0.3.4"
insta = { workspace = true }
itertools = { workspace = true }
port_scanner = { workspace = true }
pretty_assertions = { workspace = true }
Expand Down
129 changes: 128 additions & 1 deletion crates/turborepo-lib/src/engine/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -433,8 +433,16 @@ impl<'a> EngineBuilder<'a> {
};

let task_id_as_name = task_id.as_task_name();
if turbo_json.tasks.contains_key(&task_id_as_name)
if
// See if pkg#task is defined e.g. `docs#build`. This can only happen in root turbo.json
turbo_json.tasks.contains_key(&task_id_as_name)
// See if task is defined e.g. `build`. This can happen in root or workspace turbo.json
// This will fail if the user provided a task id e.g. turbo `docs#build`
|| turbo_json.tasks.contains_key(task_name)
// If user provided a task id, then we see if the task is defined
// e.g. `docs#build` should resolve if there's a `build` in root turbo.json or docs workspace level turbo.json
|| (matches!(workspace, PackageName::Root) && turbo_json.tasks.contains_key(&TaskName::from(task_name.task())))
|| (workspace == &PackageName::from(task_id.package()) && turbo_json.tasks.contains_key(&TaskName::from(task_name.task())))
{
Ok(true)
} else if !matches!(workspace, PackageName::Root) {
Expand Down Expand Up @@ -553,6 +561,7 @@ fn validate_task_name(task: Spanned<&str>) -> Result<(), Error> {
mod test {
use std::assert_matches::assert_matches;

use insta::assert_json_snapshot;
use pretty_assertions::assert_eq;
use serde_json::json;
use tempfile::TempDir;
Expand Down Expand Up @@ -680,6 +689,10 @@ mod test {
#[test_case(PackageName::from("b"), "build", "b#build", true ; "workspace task in workspace")]
#[test_case(PackageName::from("b"), "test", "b#test", true ; "task missing from workspace")]
#[test_case(PackageName::from("c"), "missing", "c#missing", false ; "task missing")]
#[test_case(PackageName::from("c"), "c#curse", "c#curse", true ; "root defined task")]
#[test_case(PackageName::from("b"), "c#curse", "c#curse", true ; "non-workspace root defined task")]
#[test_case(PackageName::from("b"), "b#special", "b#special", true ; "workspace defined task")]
#[test_case(PackageName::from("c"), "b#special", "b#special", false ; "non-workspace defined task")]
fn test_task_definition(
workspace: PackageName,
task_name: &'static str,
Expand All @@ -694,6 +707,7 @@ mod test {
"test": { "inputs": ["testing"] },
"build": { "inputs": ["primary"] },
"a#build": { "inputs": ["special"] },
"c#curse": {},
}
})),
),
Expand All @@ -702,6 +716,7 @@ mod test {
turbo_json(json!({
"tasks": {
"build": { "inputs": ["outer"]},
"special": {},
}
})),
),
Expand Down Expand Up @@ -1245,4 +1260,116 @@ mod test {
.err();
assert_eq!(result.as_deref(), reason);
}

#[test]
fn test_run_package_task_exact() {
let repo_root_dir = TempDir::with_prefix("repo").unwrap();
let repo_root = AbsoluteSystemPathBuf::new(repo_root_dir.path().to_str().unwrap()).unwrap();
let package_graph = mock_package_graph(
&repo_root,
package_jsons! {
repo_root,
"app1" => ["libA"],
"app2" => ["libA"],
"libA" => []
},
);
let turbo_jsons = vec![
(
PackageName::Root,
turbo_json(json!({
"tasks": {
"build": { "dependsOn": ["^build"] },
"special": { "dependsOn": ["^build"] },
}
})),
),
(
PackageName::from("app2"),
turbo_json(json!({
"extends": ["//"],
"tasks": {
"another": { "dependsOn": ["^build"] },
}
})),
),
]
.into_iter()
.collect();
let loader = TurboJsonLoader::noop(turbo_jsons);
let engine = EngineBuilder::new(&repo_root, &package_graph, loader, false)
.with_tasks(vec![
Spanned::new(TaskName::from("app1#special")),
Spanned::new(TaskName::from("app2#another")),
])
.with_workspaces(vec![PackageName::from("app1"), PackageName::from("app2")])
.build()
.unwrap();

let expected = deps! {
"app1#special" => ["libA#build"],
"app2#another" => ["libA#build"],
"libA#build" => ["___ROOT___"]
};
assert_eq!(all_dependencies(&engine), expected);
}

#[test]
fn test_run_package_task_exact_error() {
let repo_root_dir = TempDir::with_prefix("repo").unwrap();
let repo_root = AbsoluteSystemPathBuf::new(repo_root_dir.path().to_str().unwrap()).unwrap();
let package_graph = mock_package_graph(
&repo_root,
package_jsons! {
repo_root,
"app1" => ["libA"],
"libA" => []
},
);
let turbo_jsons = vec![
(
PackageName::Root,
turbo_json(json!({
"tasks": {
"build": { "dependsOn": ["^build"] },
}
})),
),
(
PackageName::from("app1"),
turbo_json(json!({
"extends": ["//"],
"tasks": {
"another": { "dependsOn": ["^build"] },
}
})),
),
]
.into_iter()
.collect();
let loader = TurboJsonLoader::noop(turbo_jsons);
let engine = EngineBuilder::new(&repo_root, &package_graph, loader.clone(), false)
.with_tasks(vec![Spanned::new(TaskName::from("app1#special"))])
.with_workspaces(vec![PackageName::from("app1")])
.build();
assert!(engine.is_err());
let report = miette::Report::new(engine.unwrap_err());
let mut msg = String::new();
miette::JSONReportHandler::new()
.render_report(&mut msg, report.as_ref())
.unwrap();
assert_json_snapshot!(msg);

let engine = EngineBuilder::new(&repo_root, &package_graph, loader, false)
.with_tasks(vec![Spanned::new(TaskName::from("app1#another"))])
.with_workspaces(vec![PackageName::from("libA")])
.build();
assert!(engine.is_err());
let report = miette::Report::new(engine.unwrap_err());
let mut msg = String::new();
miette::JSONReportHandler::new()
.render_report(&mut msg, report.as_ref())
.unwrap();
assert_json_snapshot!(msg);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
source: crates/turborepo-lib/src/engine/builder.rs
expression: msg
---
"{\"message\": \"missing tasks in project\",\"severity\": \"error\",\"causes\": [],\"labels\": [],\"related\": [{\"message\": \"could not find task `app1#another` in project\",\"severity\": \"error\",\"causes\": [],\"filename\": \"\",\"labels\": [],\"related\": []}]}"
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
source: crates/turborepo-lib/src/engine/builder.rs
expression: msg
---
"{\"message\": \"missing tasks in project\",\"severity\": \"error\",\"causes\": [],\"labels\": [],\"related\": [{\"message\": \"could not find task `app1#special` in project\",\"severity\": \"error\",\"causes\": [],\"filename\": \"\",\"labels\": [],\"related\": []}]}"
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,24 @@ Setup
Cached: 0 cached, 2 total
Time:\s*[\.0-9]+m?s (re)

$ ${TURBO} run cross-workspace#cross-workspace-task
\xe2\x80\xa2 Packages in scope: add-keys, add-tasks, bad-json, blank-pkg, cached, config-change, cross-workspace, invalid-config, missing-workspace-config, omit-keys, override-values, persistent (esc)
\xe2\x80\xa2 Running cross-workspace#cross-workspace-task in 12 packages (esc)
\xe2\x80\xa2 Remote caching disabled (esc)
blank-pkg:cross-workspace-underlying-task: cache hit, replaying logs 39566f6362976823
blank-pkg:cross-workspace-underlying-task:
blank-pkg:cross-workspace-underlying-task: > cross-workspace-underlying-task
blank-pkg:cross-workspace-underlying-task: > echo cross-workspace-underlying-task from blank-pkg
blank-pkg:cross-workspace-underlying-task:
blank-pkg:cross-workspace-underlying-task: cross-workspace-underlying-task from blank-pkg
cross-workspace:cross-workspace-task: cache hit, replaying logs bce507a110930f07
cross-workspace:cross-workspace-task:
cross-workspace:cross-workspace-task: > cross-workspace-task
cross-workspace:cross-workspace-task: > echo cross-workspace-task
cross-workspace:cross-workspace-task:
cross-workspace:cross-workspace-task: cross-workspace-task

Tasks: 2 successful, 2 total
Cached: 2 cached, 2 total
Time:\s*[\.0-9]+m?s >>> FULL TURBO (re)

Loading