Skip to content

Commit

Permalink
feat(query): add filter by having task (#9188)
Browse files Browse the repository at this point in the history
### Description

Adds a `has` filter that lets you check if a package has a task.

### Testing Instructions

Added tests to `command-query.t`
  • Loading branch information
NicholasLYang authored Sep 26, 2024
1 parent fde7946 commit 490e499
Show file tree
Hide file tree
Showing 8 changed files with 78 additions and 8 deletions.
15 changes: 15 additions & 0 deletions crates/turborepo-lib/src/query/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ impl<T: OutputType> FromIterator<T> for Array<T> {
#[derive(Enum, Copy, Clone, Eq, PartialEq, Debug)]
enum PackageFields {
Name,
TaskName,
DirectDependencyCount,
DirectDependentCount,
IndirectDependentCount,
Expand Down Expand Up @@ -96,6 +97,7 @@ struct PackagePredicate {
greater_than: Option<FieldValuePair>,
less_than: Option<FieldValuePair>,
not: Option<Box<PackagePredicate>>,
has: Option<FieldValuePair>,
}

impl PackagePredicate {
Expand Down Expand Up @@ -226,6 +228,14 @@ impl PackagePredicate {
}
}

fn check_has(pkg: &Package, field: &PackageFields, value: &Any) -> bool {
match (field, &value.0) {
(PackageFields::Name, Value::String(name)) => pkg.name.as_ref() == name,
(PackageFields::TaskName, Value::String(name)) => pkg.task_names().contains(name),
_ => false,
}
}

fn check(&self, pkg: &Package) -> bool {
let and = self
.and
Expand Down Expand Up @@ -254,6 +264,10 @@ impl PackagePredicate {
.as_ref()
.map(|pair| Self::check_greater_than(pkg, &pair.field, &pair.value));
let not = self.not.as_ref().map(|predicate| !predicate.check(pkg));
let has = self
.has
.as_ref()
.map(|pair| Self::check_has(pkg, &pair.field, &pair.value));

and.into_iter()
.chain(or)
Expand All @@ -262,6 +276,7 @@ impl PackagePredicate {
.chain(greater_than)
.chain(less_than)
.chain(not)
.chain(has)
.all(|p| p)
}
}
Expand Down
10 changes: 9 additions & 1 deletion crates/turborepo-lib/src/query/package.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use std::sync::Arc;
use std::{collections::HashSet, sync::Arc};

use async_graphql::Object;
use itertools::Itertools;
Expand All @@ -15,6 +15,14 @@ pub struct Package {
}

impl Package {
pub fn task_names(&self) -> HashSet<String> {
self.run
.pkg_dep_graph()
.package_json(&self.name)
.map(|json| json.scripts.keys().cloned().collect())
.unwrap_or_default()
}

pub fn direct_dependents_count(&self) -> usize {
self.run
.pkg_dep_graph()
Expand Down
1 change: 1 addition & 0 deletions crates/turborepo-lib/src/query/task.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@

Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
{
"name": "another",
"scripts": {}
"scripts": {
"dev": "echo building"
}
}
3 changes: 2 additions & 1 deletion turborepo-tests/integration/tests/command-ls.t
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,8 @@ Run info on package `another`
WARNING ls command is experimental and may change in the future
another depends on: <no packages>

tasks: <no tasks>
tasks:
dev: echo building


Run info on package `my-app`
Expand Down
39 changes: 39 additions & 0 deletions turborepo-tests/integration/tests/command-query.t
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,45 @@ Query packages that have at least one dependent package
}
}
Query packages that have a task named `build`
$ ${TURBO} query "query { packages(filter: { has: { field: TASK_NAME, value: \"build\" } }) { items { name } } }" | jq
WARNING query command is experimental and may change in the future
{
"data": {
"packages": {
"items": [
{
"name": "my-app"
},
{
"name": "util"
}
]
}
}
}
Query packages that have a task named `build` or `dev`
$ ${TURBO} query "query { packages(filter: { or: [{ has: { field: TASK_NAME, value: \"build\" } }, { has: { field: TASK_NAME, value: \"dev\" } }] }) { items { name } } }" | jq
WARNING query command is experimental and may change in the future
{
"data": {
"packages": {
"items": [
{
"name": "another"
},
{
"name": "my-app"
},
{
"name": "util"
}
]
}
}
}
Get dependents of `util`
$ ${TURBO} query "query { packages(filter: { equal: { field: NAME, value: \"util\" } }) { items { directDependents { items { name } } } } }" | jq
WARNING query command is experimental and may change in the future
Expand Down
10 changes: 5 additions & 5 deletions turborepo-tests/integration/tests/edit-turbo-json/task.t
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ Baseline task hashes
$ ${TURBO} build --dry=json | jq -r '.tasks | sort_by(.taskId)[] | {taskId, hash}'
{
"taskId": "another#build",
"hash": "3639431fdcdf9f9e"
"hash": "e9a99dd97d223d88"
}
{
"taskId": "my-app#build",
Expand All @@ -22,7 +22,7 @@ Change only my-app#build
$ ${TURBO} build --dry=json | jq -r '.tasks | sort_by(.taskId)[] | {taskId, hash}'
{
"taskId": "another#build",
"hash": "3639431fdcdf9f9e"
"hash": "e9a99dd97d223d88"
}
{
"taskId": "my-app#build",
Expand All @@ -38,7 +38,7 @@ Change my-app#build dependsOn
$ ${TURBO} build --dry=json | jq -r '.tasks | sort_by(.taskId)[] | {taskId, hash}'
{
"taskId": "another#build",
"hash": "3639431fdcdf9f9e"
"hash": "e9a99dd97d223d88"
}
{
"taskId": "my-app#build",
Expand All @@ -54,7 +54,7 @@ Non-materially modifying the dep graph does nothing.
$ ${TURBO} build --dry=json | jq -r '.tasks | sort_by(.taskId)[] | {taskId, hash}'
{
"taskId": "another#build",
"hash": "3639431fdcdf9f9e"
"hash": "e9a99dd97d223d88"
}
{
"taskId": "my-app#build",
Expand All @@ -71,7 +71,7 @@ Change util#build impacts itself and my-app
$ ${TURBO} build --dry=json | jq -r '.tasks | sort_by(.taskId)[] | {taskId, hash}'
{
"taskId": "another#build",
"hash": "3639431fdcdf9f9e"
"hash": "e9a99dd97d223d88"
}
{
"taskId": "my-app#build",
Expand Down
4 changes: 4 additions & 0 deletions turborepo-tests/integration/tests/no-args.t
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,8 @@ Run without any tasks, get a list of potential tasks to run
my-app, util
maybefails
my-app, util
dev
another
[1]

Run again with a filter and get only the packages that match
Expand Down Expand Up @@ -176,6 +178,8 @@ Initialize a new monorepo
cross-workspace
cross-workspace-underlying-task
blank-pkg
dev
another
missing-workspace-config-task
missing-workspace-config
missing-workspace-config-task-with-deps
Expand Down

0 comments on commit 490e499

Please sign in to comment.