Skip to content

Build R packages with bundled libuv and verify them - #129

Open
benjaminguttmann-avtq wants to merge 2 commits into
mainfrom
r-bundled-libuv
Open

benjaminguttmann-avtq wants to merge 2 commits into
mainfrom
r-bundled-libuv

Conversation

@benjaminguttmann-avtq

@benjaminguttmann-avtq benjaminguttmann-avtq commented Nov 5, 2026 •

Copy link
Copy Markdown
Contributor

Problem

fs >= 2.0.0 (pulled in by shiny via sass/bslib) needs libuv headers, which the cflinuxfs stacks do not ship. The fs install failed, and because R exits 0 when install.packages fails for a dependency, the build still succeeded. As a result shiny and its dependencies were missing from the r 4.6.2 artifacts.

Changes

  • internal/recipe/r.go
    • Run all R package installs (remotes, explicit deps, sub-deps) with USE_BUNDLED_LIBUV=1 via RunWithEnv, so fs builds its vendored libuv.
    • Add a verification step after the sub-dependency installs and before remove.packages("remotes"). It fails the build unless fs, the explicit deps (cli, curl, lifecycle, R6, rlang, withr, processx, callr, stringr) and the sub-deps (Rserve, forecast, shiny, plumber) can be loaded with requireNamespace. This catches both missing packages and broken native builds.
    • Introduce rExplicitDeps so the install and verification steps share one package list.
  • Tests (recipe_compiled_test.go, new export_test.go)
    • Every package install sets USE_BUNDLED_LIBUV=1.
    • Verification runs before remotes is removed and covers fs, the explicit deps and the sub-deps.
    • The build fails with verifying installed R packages when verification fails.

Testing

  • go test -race ./internal/recipe/ -run 'TestRRecipe|TestRserve' passes.
  • Not run: the R verification snippet against a real R install, and a Docker/parity build of the r artifact. Please confirm via CI or make parity-test DEP=r.
  • TestLibunwindRecipeBuild fails locally on macOS (trailing slash in TMPDIR). It fails the same way on main and is unrelated to this change.

Notes for reviewers

  • Verification uses requireNamespace, which loads each package. It is slightly slower than installed.packages() but checks the failure this PR targets.
  • The verify call uses plain Run, because it needs no extra environment.

Should fix the failing tests in cloudfoundry/r-buildpack#400

fs >= 2.0.0 requires libuv headers that the stacks do not ship, so shiny and
its dependencies silently failed to install (R exits 0 on dependency
failures) and were missing from the r 4.6.2 artifacts.

- Set USE_BUNDLED_LIBUV=1 for all R package installs.
- Fail the build if fs, Rserve, forecast, shiny or plumber are not installed.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

FakeRunner-only coverage leaves bundled-libuv compilation, namespace loading, and exit-status propagation unverified in a real R/parity build on the target stacks.

No open issues 🎉

What changed in this PR

This PR updates the R recipe to use bundled libuv during package installation and fail the build when required packages cannot load, preventing incomplete R artifacts.

Changes:

  • Sets USE_BUNDLED_LIBUV=1 for all R package installs.
  • Shares the explicit dependency list between installation and verification, which runs before removing remotes.
  • Adds tests for the install environment, verification ordering and package coverage, and verification failure handling.
File Description
internal/​recipe/​recipe_compiled_test.go Tests bundled-libuv settings and package verification behavior.
internal/​recipe/​r.go Enables bundled libuv and verifies required packages before packaging.
internal/​recipe/​export_test.go Exposes the verification command to external-package tests.

Review effort: Balanced

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants