Implement steps 3 + 4 of issue #115 on top of the failure classifier, now that bincraft v4.4.3 applies registry patches/makevars/configure_args to the target build (not just dependencies), so a trial patched build is meaningful. - refactor the classify helpers to expose a pure build_triage_report() and a list-returning entry builder; failing-builds-report.R now renders from it - add local/propose-patches.R (step 3, "propose, do not apply"): emit a pre-filled registry.json entry for each classified, safe, unregistered failure, validate the candidate set against a temporary merged registry, and (only on request) --write it plus a proposals ledger, or --open-issue a Forgejo tracking issue; the human gate and validator/trial-build acceptance stay, and novel source diffs / unknown signatures are never proposed - add local/trial-build-patch.R: isolated bincraft build of one package with the registry applied (no upload/archive/metadata) as the pre-merge gate - add local/proposal-tracking.R + local/proposal-tracking-lib.R (step 4): signature hit rate, proposed-vs-merged, and retirement candidates, with the pure helpers covered by tests - teach validate-patches.R optional PATCH_DIR/REGISTRY_FILE overrides so a candidate registry can be validated without touching the real one - document the propose/trial-build/tracking workflow in local/patches/README.md
105 lines
3.3 KiB
R
105 lines
3.3 KiB
R
source(file.path("..", "proposal-tracking-lib.R"))
|
|
source(file.path("..", "failing-builds-classify.R"))
|
|
|
|
mk_failures <- function() {
|
|
data.frame(
|
|
name = c("StanHeaders", "rstan", "RcppParallel", "somepkg"),
|
|
platform = c("alpine-321", "alpine-321", "alpine-320", "redhat-9"),
|
|
arch = c("amd64", "arm64", "amd64", "amd64"),
|
|
error_text = c(
|
|
"fatal error: tbb/tbb_stddef.h: No such file or directory",
|
|
"In file: tbb/tbb_stddef.h: No such file or directory",
|
|
"Error: USE_TBB=Linux is not supported; bundled TBB on musl",
|
|
"some unmatched failure"
|
|
),
|
|
stringsAsFactors = FALSE
|
|
)
|
|
}
|
|
|
|
test_that("merge_ledger appends new proposals and preserves existing history", {
|
|
existing <- list(list(
|
|
package = "fs",
|
|
signature = "system-libuv-link-leak",
|
|
status = "merged"
|
|
))
|
|
new <- list(
|
|
list(
|
|
package = "fs",
|
|
signature = "system-libuv-link-leak",
|
|
status = "proposed"
|
|
),
|
|
list(
|
|
package = "StanHeaders",
|
|
signature = "tbb-stddef-removed",
|
|
status = "proposed"
|
|
)
|
|
)
|
|
merged <- merge_ledger(existing, new)
|
|
expect_length(merged, 2L) # fs is deduped, StanHeaders added
|
|
fs <- Filter(function(r) r$package == "fs", merged)[[1L]]
|
|
expect_identical(fs$status, "merged") # existing status preserved, not clobbered
|
|
})
|
|
|
|
test_that("merge_ledger handles an empty/NULL starting ledger", {
|
|
new <- list(list(package = "x", signature = "s"))
|
|
expect_length(merge_ledger(NULL, new), 1L)
|
|
expect_length(merge_ledger(list(), new), 1L)
|
|
})
|
|
|
|
test_that("signature_hit_rate splits addressed vs open per signature", {
|
|
report <- build_triage_report(mk_failures(), registered_pkgs = "RcppParallel")
|
|
hit <- signature_hit_rate(report, registered_pkgs = "RcppParallel")
|
|
tbb <- Filter(function(h) h$signature == "tbb-stddef-removed", hit)[[1L]]
|
|
expect_identical(tbb$packages, 2L) # StanHeaders + rstan
|
|
expect_identical(tbb$addressed, 0L)
|
|
expect_identical(tbb$open, 2L)
|
|
expect_true(tbb$auto_proposable)
|
|
|
|
rcpp <- Filter(function(h) h$signature == "rcppparallel-bundled-tbb", hit)[[
|
|
1L
|
|
]]
|
|
expect_identical(rcpp$addressed, 1L) # already registered
|
|
expect_identical(rcpp$open, 0L)
|
|
|
|
# Unclassified failures never appear as a signature.
|
|
expect_false(
|
|
"unclassified" %in% vapply(hit, function(h) h$signature, character(1L))
|
|
)
|
|
})
|
|
|
|
test_that("proposed_vs_merged marks a package merged once it is registered", {
|
|
ledger <- list(
|
|
list(
|
|
package = "StanHeaders",
|
|
signature = "tbb-stddef-removed",
|
|
status = "proposed"
|
|
),
|
|
list(
|
|
package = "rstan",
|
|
signature = "tbb-stddef-removed",
|
|
status = "proposed"
|
|
)
|
|
)
|
|
pvm <- proposed_vs_merged(ledger, registered_pkgs = "StanHeaders")
|
|
expect_identical(pvm$total, 2L)
|
|
expect_identical(pvm$merged, 1L)
|
|
stan <- Filter(function(r) r$package == "StanHeaders", pvm$records)[[1L]]
|
|
expect_identical(stan$status, "merged")
|
|
})
|
|
|
|
test_that("retirement_candidates flags entries whose package no longer fails", {
|
|
entries <- list(
|
|
list(package = "RcppParallel"),
|
|
list(package = "oldpkg")
|
|
)
|
|
# RcppParallel still fails; oldpkg does not -> only oldpkg is retirable.
|
|
out <- retirement_candidates(
|
|
entries,
|
|
failing_pkgs = c("RcppParallel", "StanHeaders")
|
|
)
|
|
expect_identical(out, "oldpkg")
|
|
expect_length(
|
|
retirement_candidates(entries, failing_pkgs = c("RcppParallel", "oldpkg")),
|
|
0L
|
|
)
|
|
})
|