feat(local): detect dependency-cascade failures generally, not just RcppParallel

The first trial-build gate run correctly went red: the 10 auto-proposed
tbb-stddef packages (BFpack, BayesERtools, GMLTM, ...) all fail while building
their shared `rstan` dependency, not in their own code -- the `tbb/tbb_stddef.h`
error is in rstan's Module.cpp. So a per-package makevars entry is useless for
them; they are blocked on rstan (which already has an entry). This is the same
cascade the RcppParallel `applies_to` guard catches, but the tbb-stddef
signature is generic and had no such pin.

Add `failing_dependency(error_text, package)`: when the log shows a DIFFERENT
package failed to compile ("Failed to build source package X", "compilation
failed for package 'X'", ...), that package is the real cause. build_triage_report
now blocks any package whose every failing build is such a cascade -- reported
as blocked_on the dependency, never proposed a bogus entry. A package that fails
in its OWN compilation is still proposed. This unifies the applies_to and
data-driven cases into one `blocked_packages` / `blocked_on` model.

- report/proposer/blocked_summary now count the actually-blocked packages
- blocked note shows even when a group also has genuine proposals
- tests cover the rstan-cascade vs own-compile split (with the real log strings)
This commit is contained in:
Patrick Schratz 2026-07-15 21:33:54 +00:00
commit c98aaa548f
No known key found for this signature in database
GPG key ID: 62050D5BC68AB6DC

View file

@ -105,6 +105,49 @@ test_that("RcppParallel dependents are blocked, not proposed a per-package patch
expect_identical(grp$blocked_on, "RcppParallel")
})
test_that("failing_dependency names the dependency that actually failed", {
# A leaf package (BFpack) that fails building its rstan dependency.
txt <- paste(
"Error in installing dependencies for package BFpack with tag 1.6.1",
"Failed to build source package rstan.",
"ERROR: compilation failed for package rstan",
sep = "\n"
)
expect_identical(failing_dependency(txt, "BFpack"), "rstan")
# A package failing in its OWN compilation is not a cascade.
own <- "ERROR: compilation failed for package BFpack"
expect_true(is.na(failing_dependency(own, "BFpack")))
expect_true(is.na(failing_dependency(NA_character_, "x")))
expect_true(is.na(failing_dependency("some unrelated error", "x")))
})
test_that("Stan packages blocked on rstan are not proposed a per-package entry", {
# BFpack/GMLTM fail building rstan; the tbb error is in rstan's compile.
cascade <- paste(
"Failed to build source package rstan.",
"fatal error: tbb/tbb_stddef.h: No such file or directory",
sep = "\n"
)
failures <- data.frame(
name = c("BFpack", "GMLTM", "someOwnPkg"),
platform = "ubuntu-2604",
arch = "amd64",
error_text = c(
cascade,
cascade,
# someOwnPkg fails in its OWN compile on the same header -> fixable.
"someOwnPkg.cpp: fatal error: tbb/tbb_stddef.h: No such file or directory"
),
stringsAsFactors = FALSE
)
report <- build_triage_report(failures, registered_pkgs = character(0L))
grp <- Filter(function(g) g$signature == "tbb-stddef-removed", report)[[1L]]
# Only the own-compile package is proposed; the rstan cascades are blocked.
expect_identical(names(grp$proposed_entries), "someOwnPkg")
expect_setequal(grp$blocked_packages, c("BFpack", "GMLTM"))
expect_identical(grp$blocked_on, "rstan")
})
test_that("RcppParallel itself is still proposed when it is the failing package", {
failures <- data.frame(
name = "RcppParallel",