Skip to content

Commit

Permalink
[antlir2][errors] library to integrate with buck2 action error handler
Browse files Browse the repository at this point in the history
Summary:
Library to make it easier to integrate with buck2 action error handlers
https://www.internalfb.com/intern/staticdocs/buck2/docs/rule_authors/action_error_handler/

Test Plan: See rest of stack

Reviewed By: sergeyfd

Differential Revision: D59243780

fbshipit-source-id: ed4a5d11e5609900488f2d02a211ff16f831e66b
  • Loading branch information
vmagro authored and facebook-github-bot committed Jul 3, 2024
1 parent 0b100dc commit b8fbd7f
Show file tree
Hide file tree
Showing 3 changed files with 96 additions and 0 deletions.
13 changes: 13 additions & 0 deletions antlir/antlir2/antlir2_error_handler/BUCK
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
load("//antlir/bzl:build_defs.bzl", "rust_library")

oncall("antlir")

rust_library(
name = "antlir2_error_handler",
srcs = glob(["src/**/*.rs"]),
deps = [
"serde",
"serde_json",
"typed-builder",
],
)
25 changes: 25 additions & 0 deletions antlir/antlir2/antlir2_error_handler/handler.bzl
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Copyright (c) Meta Platforms, Inc. and affiliates.
#
# This source code is licensed under the MIT license found in the
# LICENSE file in the root directory of this source tree.

def antlir2_error_handler(ctx: ActionErrorCtx) -> list[ActionSubError]:
errors = []

for line in ctx.stderr.splitlines():
if line.startswith("antlir2_error_handler: "):
err = line.removeprefix("antlir2_error_handler: ")
err = json.decode(err)
errors.append(ctx.new_sub_error(
category = err["category"],
message = err.get("message", None),
locations = [
ctx.new_error_location(
file = loc["file"],
line = loc.get("line", None),
)
for loc in err.get("locations", [])
],
))

return errors
58 changes: 58 additions & 0 deletions antlir/antlir2/antlir2_error_handler/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

//! Rust side of Buck2's action error handlers.
//!
//! Provides a standard way to report structured errors from Rust and keep that
//! structure in Buck2.
//!
//! Today, these error details only appear in Buck2 datasets and build reports,
//! but should appear more prominently in the buck2 cli/ui in the future.
//!
//! https://www.internalfb.com/intern/staticdocs/buck2/docs/rule_authors/action_error_handler/

use std::fmt::Display;

use serde::Serialize;
use typed_builder::TypedBuilder;

#[derive(TypedBuilder, Debug, Clone, Serialize)]
pub struct SubError {
#[builder(setter(transform=|s: impl Display| s.to_string()))]
category: String,
#[builder(default, setter(transform=|s: impl Display| Some(s.to_string())))]
message: Option<String>,
#[builder(default)]
locations: Vec<Location>,
}

#[derive(TypedBuilder, Debug, Clone, Serialize)]
pub struct Location {
file: String,
#[builder(default, setter(strip_option))]
line: Option<u32>,
}

impl SubError {
pub fn from_err(category: impl Display, err: impl std::error::Error) -> Self {
Self {
category: category.to_string(),
message: Some(err.to_string()),
locations: Default::default(),
}
}

pub fn log(&self) {
// Dump this to stderr. Unfortunately the action error handler only gets
// access to the stdout/err text and not any other artifacts, so we have
// to deal with it being mixed in with other output, hence this prefix.
eprintln!(
"antlir2_error_handler: {}",
serde_json::to_string(self).expect("SubError is always json-serializable")
);
}
}

0 comments on commit b8fbd7f

Please sign in to comment.