Commit graph build-cran-binaries/local/trial-build-registry.R
Author SHA1 Message Date
118a92889f fix(local): make the trial-build gate detect non-throwing build failures (#130)
Some checks failed
ci/crow/cron/process-updates/2 Pipeline was successful
ci/crow/cron/process-updates/7 Pipeline was successful
ci/crow/cron/process-updates/8 Pipeline was successful
ci/crow/cron/process-updates/9 Pipeline was successful
ci/crow/cron/process-updates/3 Pipeline was successful
ci/crow/cron/process-updates/4 Pipeline was successful
ci/crow/cron/process-updates/10 Pipeline was successful
ci/crow/cron/process-updates/13 Pipeline was successful
ci/crow/manual/build-all-versions-install-deps/2 Pipeline was successful
ci/crow/cron/process-updates/14 Pipeline was successful
ci/crow/cron/process-updates/15 Pipeline was successful
ci/crow/cron/process-updates/16 Pipeline was successful
ci/crow/cron/process-updates/11 Pipeline was successful
ci/crow/cron/process-updates/18 Pipeline was successful
ci/crow/cron/process-updates/17 Pipeline was successful
ci/crow/cron/process-updates/5 Pipeline was successful
ci/crow/cron/process-updates/12 Pipeline was successful
ci/crow/manual/auto-apply-patches Pipeline was successful
ci/crow/cron/process-updates/6 Pipeline was successful
ci/crow/cron/process-updates/1 Pipeline was successful
ci/crow/manual/build-all-versions/7 Pipeline failed
ci/crow/manual/build-all-versions/8 Pipeline failed
ci/crow/manual/build-all-versions/5 Pipeline failed
ci/crow/manual/build-all-versions/6 Pipeline failed
## Critical: the gate was false-green

The latest run printed **`3/3 passed on alpine-324`** while all three builds actually **failed** (their `rstan` dependency won't compile). A false-green gate would let broken registry entries merge — worse than no gate.

Root cause: `bincraft::build_binary_package()` catches build failures internally and **returns `"error"`** for the failed tag rather than throwing. The gate's `tryCatch` only treated a *thrown* exception as failure, so every non-throwing failure looked like a pass.

Fix: inspect the return value. A tag passes only if the flattened result is non-empty and contains no `"error"` sentinel; a thrown error still counts as failure. Verified the verdict against `error`/`skipped`/`TRUE`/`list(success=TRUE)`/`NULL`/mixed inputs.

With this, the current rstan-blocked entries will correctly show **0/3 (red)** — which is the right answer until rstan builds.

Reviewed-on: #130
2026-07-16 08:24:03 +00:00
ff9f5f5177 fix(local): shell-quote git args in the auto-patch push and trial-build gate (#126)
Some checks failed
ci/crow/cron/process-updates/7 Pipeline was successful
ci/crow/manual/trial-build-registry/13 Pipeline was successful
ci/crow/manual/trial-build-registry/15 Pipeline was successful
ci/crow/manual/trial-build-registry/11 Pipeline was successful
ci/crow/manual/trial-build-registry/7 Pipeline was successful
ci/crow/manual/trial-build-registry/9 Pipeline was successful
ci/crow/manual/trial-build-registry/1 Pipeline was successful
ci/crow/manual/trial-build-registry/5 Pipeline was successful
ci/crow/manual/trial-build-registry/3 Pipeline was successful
ci/crow/cron/process-updates/9 Pipeline was successful
ci/crow/manual/trial-build-registry/17 Pipeline was successful
ci/crow/cron/process-updates/1 Pipeline failed
ci/crow/cron/process-updates/3 Pipeline was successful
ci/crow/manual/build-all-versions/8 Pipeline failed
ci/crow/manual/build-all-versions/7 Pipeline failed
ci/crow/cron/process-updates/2 Pipeline failed
ci/crow/manual/build-all-versions/6 Pipeline failed
ci/crow/manual/build-all-versions/5 Pipeline failed
ci/crow/manual/trial-build-registry/8 Pipeline was successful
ci/crow/manual/trial-build-registry/2 Pipeline was successful
ci/crow/manual/trial-build-registry/10 Pipeline was successful
ci/crow/manual/trial-build-registry/14 Pipeline was successful
ci/crow/manual/trial-build-registry/12 Pipeline was successful
ci/crow/manual/trial-build-registry/16 Pipeline was successful
ci/crow/manual/trial-build-registry/6 Pipeline was successful
ci/crow/manual/trial-build-registry/4 Pipeline was successful
ci/crow/cron/process-updates/8 Pipeline was successful
ci/crow/manual/trial-build-registry/18 Pipeline was successful
ci/crow/cron/process-updates/4 Pipeline was successful
ci/crow/cron/process-updates/10 Pipeline was successful
## Problem

The first real `auto-apply-patches` run classified, limited to the top-10, and validated the candidate registry cleanly, then died at the push step:

```
Validating candidate registry:
  Patch registry OK (13 entries).
sh: syntax error: unexpected "("
Error in git("commit", "-m", ...): git commit -m feat(patches): auto-propose 10 registry entries ... failed
```

Root cause: R's `system2()` with captured output (`stdout=TRUE`) runs the command through `/bin/sh`, and the arguments were passed **unquoted**. The commit message `feat(patches): ...` contains `()`, which the shell tried to interpret. The same class of bug affects the `^{commit}` and `ref:path` git refs in the trial-build gate.

## Fix

`shQuote()` every git argument:
- `propose-patches.R` -- the `git()` helper used by `--open-pr` (commit, push, checkout).
- `trial-build-registry.R` -- the base-ref reads (`rev-parse ... ^{commit}`, `ls-tree`, `show ref:path`).

## Verification

- Reproduced against a real git repo: the unquoted call fails with status 2 (the same `unexpected "("`); the `shQuote`d call commits successfully, and `rev-parse HEAD^{commit}` resolves.
- 105 tests pass; all pre-commit hooks pass.

Everything else in that run was correct: 842,659 failing builds classified, RcppParallel's 895 dependents correctly reported as blocked (not proposed), top-10 tbb-stddef candidates selected, 69 deferred, registry validated. Only the shell quoting was broken.

Reviewed-on: #126
2026-07-15 15:43:02 +00:00
4bca17e4ac feat(local): auto-apply registry patches with a build-env trial-build gate (#124)
All checks were successful
ci/crow/cron/process-updates/14 Pipeline was successful
ci/crow/cron/process-updates/13 Pipeline was successful
ci/crow/cron/process-updates/16 Pipeline was successful
ci/crow/cron/process-updates/18 Pipeline was successful
ci/crow/cron/process-updates/15 Pipeline was successful
ci/crow/cron/process-updates/12 Pipeline was successful
ci/crow/cron/process-updates/17 Pipeline was successful
ci/crow/cron/process-updates/6 Pipeline was successful
ci/crow/cron/process-updates/5 Pipeline was successful
ci/crow/cron/process-updates/11 Pipeline was successful
ci/crow/cron/process-updates/1 Pipeline was successful
ci/crow/cron/process-updates/2 Pipeline was successful
ci/crow/cron/process-updates/7 Pipeline was successful
ci/crow/cron/process-updates/8 Pipeline was successful
Closes the classifier loop (issue #115, step 3): turns the auto-proposable candidates into an actual PR, gated by a real trial build **in our own build-env images**.

Chosen model (from the design discussion): **autonomous PR**, **PR-first with a CI trial-build gate**, **bounded top-N batch** per run.

## Creating the patch PR

- `propose-patches.R` gains:
  - `--limit N` -- act on the top-N candidates by failure volume; the rest defer to the next run (logged).
  - `--open-pr` -- write the entries onto the reused `auto/registry-patch-proposals` branch, push (with `REPO_RW_TOKEN`), and open/update **one** PR via the Forgejo API (so re-runs update the same PR instead of piling up).
- `.crow/auto-apply-patches.yaml` -- a single job that runs `--open-pr --limit` on a cron/manual trigger. Needs `FORGEJO_TOKEN` + a write-scoped `REPO_RW_TOKEN`.

Novel source diffs and unknown signatures are still never proposed; nothing merges.

## The merge gate (our build-env images)

- `.crow/trial-build-registry.yaml` -- matrixed over the real `OS/IMG` build-env matrix (alpine:3.24, redhat:8/9/10, ubuntu:jammy/noble/**resolute** for ubuntu-2604). Each platform runs `local/trial-build-registry.R`, which diffs the branch registry against `main` and trial-builds **only the entries the branch adds** that apply to that platform, inside `reg.devxy.io/rpkgs/build-env-*`. Green only if every new entry builds; a platform with no new entries is a fast no-op. Nothing is uploaded/archived/recorded.
- The base-registry read **fails loud** if it can't read `registry.json` at `main`, rather than silently treating the base as empty and trial-building the whole registry.

## Notes / follow-up

- The repo uses **no `pull_request` triggers**, so the gate runs manually or on a cron against the branch (`--var patch_branch=...`). Wiring it to fire automatically on the PR needs `event: pull_request` enabled on the Forgejo webhook -- a one-line addition once that's on.
- Two new crons to register in the crow UI: `auto-apply-patches` and `trial-build-registry`. New secret needed: `REPO_RW_TOKEN` (write scope) for the push.

## Verification

- New pure helpers `entry_applies_to_os()` / `new_registry_packages()` covered by tests (platform codename/family/wildcard matching; added-vs-unchanged entry detection; per-platform filtering).
- `--limit` smoke (stubbed DB): top-2 by volume proposed, 3 deferred, candidate registry validates.
- Full suite: 105 tests pass; all pre-commit hooks pass (air, prettier, markdownlint, yamllint, validate-patches).

Reviewed-on: #124
2026-07-15 08:28:15 +00:00