Skip to content

Commit eaaa1a9

Browse files
committed
Allow BXLs to aquery actions directly; used for action debugging.
facebook#1250
1 parent c394cfe commit eaaa1a9

6 files changed

Lines changed: 91 additions & 1 deletion

File tree

app/buck2_build_api/src/query/bxl.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ use std::future::Future;
1212
use std::pin::Pin;
1313

1414
use async_trait::async_trait;
15+
use buck2_artifact::actions::key::ActionKey;
1516
use buck2_core::cells::CellResolver;
1617
use buck2_core::cells::name::CellName;
1718
use buck2_core::configuration::compatibility::MaybeCompatible;
@@ -182,6 +183,11 @@ pub trait BxlAqueryFunctions: Send {
182183
dice: &mut DiceComputations<'_>,
183184
targets: &TargetSet<ActionQueryNode>,
184185
) -> buck2_error::Result<TargetSet<ActionQueryNode>>;
186+
async fn get_action_nodes(
187+
&self,
188+
dice: &mut DiceComputations<'_>,
189+
action_keys: Vec<ActionKey>,
190+
) -> buck2_error::Result<TargetSet<ActionQueryNode>>;
185191
}
186192

187193
pub static NEW_BXL_CQUERY_FUNCTIONS: LateBinding<

app/buck2_bxl/src/bxl/starlark_defs/aquery.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
*/
1010

1111
use allocative::Allocative;
12+
use buck2_artifact::actions::key::ActionKey;
1213
use buck2_build_api::actions::query::ActionQueryNode;
1314
use buck2_build_api::query::bxl::BxlAqueryFunctions;
1415
use buck2_build_api::query::bxl::NEW_BXL_AQUERY_FUNCTIONS;
@@ -46,6 +47,7 @@ use starlark::values::type_repr::StarlarkTypeRepr;
4647

4748
use crate::bxl::starlark_defs::context::BxlContext;
4849
use crate::bxl::starlark_defs::context::ErrorPrinter;
50+
use crate::bxl::starlark_defs::nodes::action::StarlarkAction;
4951
use crate::bxl::starlark_defs::nodes::action::StarlarkActionQueryNode;
5052
use crate::bxl::starlark_defs::providers_expr::AnyProvidersExprArg;
5153
use crate::bxl::starlark_defs::providers_expr::ProvidersExpr;
@@ -123,6 +125,7 @@ enum UnpackActionNodes<'v> {
123125
ActionQueryNodesSet(&'v StarlarkTargetSet<ActionQueryNode>),
124126
ConfiguredProviders(AnyProvidersExprArg<'v>),
125127
ConfiguredTargets(ConfiguredTargetListExprArg<'v>),
128+
StarlarkActions(UnpackList<StarlarkAction>),
126129
}
127130

128131
// Aquery operates on `ActionQueryNode`s. Under the hood, the target set of action query nodes is obtained
@@ -141,6 +144,14 @@ async fn unpack_action_nodes<'v>(
141144
return Ok(action_nodes.into_iter().map(|v| v.0).collect());
142145
}
143146
UnpackActionNodes::ActionQueryNodesSet(action_nodes) => return Ok(action_nodes.0.clone()),
147+
UnpackActionNodes::StarlarkActions(actions) => {
148+
let action_keys: Vec<ActionKey> = actions
149+
.into_iter()
150+
.map(|starlark_action| starlark_action.0.key().dupe())
151+
.collect();
152+
153+
return aquery_env.get_action_nodes(dice, action_keys).await;
154+
}
144155
UnpackActionNodes::ConfiguredProviders(arg) => {
145156
ProvidersExpr::<ConfiguredProvidersLabel>::unpack(
146157
arg,
@@ -183,6 +194,11 @@ async fn unpack_action_nodes<'v>(
183194
///
184195
/// Query results are `target_set`s of `action_query_node`s, which supports iteration,
185196
/// indexing, `len()`, set addition/subtraction, and `equals()`.
197+
///
198+
/// Actions can be specified as:
199+
/// - Target expressions (configured targets/providers)
200+
/// - Existing action query nodes or target sets
201+
/// - `bxl.Action` objects (obtained from `ctx.audit().output()`)
186202
#[starlark_module]
187203
fn aquery_methods(builder: &mut MethodsBuilder) {
188204
/// The deps query for finding the transitive closure of dependencies.

app/buck2_query_impls/src/aquery/bxl.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ use std::marker::PhantomData;
1212
use std::sync::Arc;
1313

1414
use async_trait::async_trait;
15+
use buck2_artifact::actions::key::ActionKey;
1516
use buck2_build_api::actions::query::ActionQueryNode;
1617
use buck2_build_api::analysis::calculation::RuleAnalysisCalculation;
1718
use buck2_build_api::query::bxl::BxlAqueryFunctions;
@@ -302,6 +303,24 @@ impl BxlAqueryFunctions for BxlAqueryFunctionsImpl {
302303
})
303304
.await
304305
}
306+
307+
async fn get_action_nodes(
308+
&self,
309+
dice: &mut DiceComputations<'_>,
310+
action_keys: Vec<ActionKey>,
311+
) -> buck2_error::Result<TargetSet<ActionQueryNode>> {
312+
dice.with_linear_recompute(|dice| async move {
313+
let delegate = self.aquery_delegate(&dice).await?;
314+
let mut result = TargetSet::new();
315+
let nodes = buck2_util::future::try_join_all(
316+
action_keys.iter().map(|key| delegate.get_action_node(&key)),
317+
)
318+
.await?;
319+
result.extend(nodes);
320+
Ok(result)
321+
})
322+
.await
323+
}
305324
}
306325

307326
pub(crate) fn init_new_bxl_aquery_functions() {

tests/core/query/aquery/test_aquery.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,3 +154,16 @@ async def test_bxl_aquery_eval(buck: Buck) -> None:
154154
@buck_test()
155155
async def test_bxl_aquery_action_query_node(buck: Buck) -> None:
156156
await buck.bxl("//:aquery.bxl:action_query_node")
157+
158+
159+
# Tests for bxl.Action support in aquery operations
160+
@buck_test()
161+
async def test_bxl_action_deps_0(buck: Buck) -> None:
162+
"""Test passing a bxl.Action to aquery.deps() with depth=0 returns itself"""
163+
await buck.bxl("//:aquery.bxl:action_deps_0")
164+
165+
166+
@buck_test()
167+
async def test_bxl_action_deps(buck: Buck) -> None:
168+
"""Test that you can isolate the deps of one action by itself"""
169+
await buck.bxl("//:aquery.bxl:action_deps")

tests/core/query/aquery/test_aquery_data/aquery.bxl

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,3 +141,38 @@ action_query_node = bxl_main(
141141
impl = _impl_action_query_node,
142142
cli_args = {},
143143
)
144+
145+
def _impl_action_deps_0(ctx):
146+
"""Test passing a bxl.Action to aquery.deps() returns itself"""
147+
nodes = ctx.aquery().eval("//:test")
148+
149+
action = nodes[0].action()
150+
151+
# Pass the bxl.Action rather than a target to aquery.deps()
152+
result = ctx.aquery().deps([action], depth = 0)
153+
_assert_eq(action.outputs(), result[0].action().outputs())
154+
155+
action_deps_0 = bxl_main(
156+
impl = _impl_action_deps_0,
157+
cli_args = {},
158+
)
159+
160+
def _impl_action_deps(ctx):
161+
"""Test that you can isolate the deps of one action by itself"""
162+
nodes = ctx.aquery().eval("//:test")
163+
164+
action = nodes[0].action()
165+
166+
# Pass the bxl.Action rather than a target to aquery.deps()
167+
result = ctx.aquery().deps([action], depth = 1)
168+
169+
_assert_eq(len(result), 2)
170+
# First should be itself
171+
_assert_eq(action.outputs(), result[0].action().outputs())
172+
dep = result[1]
173+
_assert_eq(dep.action().outputs()[0].short_path, "dep")
174+
175+
action_deps = bxl_main(
176+
impl = _impl_action_deps,
177+
cli_args = {},
178+
)

tests/core/query/aquery/test_aquery_data/prelude.bzl

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
def _test(ctx: AnalysisContext):
1010
dep = ctx.actions.write("dep", "")
1111
default = ctx.actions.copy_file("default", dep)
12+
other_default = ctx.actions.copy_file("other_default", dep)
1213
other = ctx.actions.write("other", "")
1314

1415
sub_default = ctx.actions.write("sub_default", "")
@@ -18,7 +19,7 @@ def _test(ctx: AnalysisContext):
1819
ctx.actions.write("unused", "")
1920

2021
return [DefaultInfo(
21-
default_outputs = [default],
22+
default_outputs = [default, other_default],
2223
other_outputs = [other],
2324
sub_targets = {
2425
"sub": [

0 commit comments

Comments
 (0)