refactor: migrate package installation from pak to uvr #147

Merged
pat-s merged 2 commits from t3code/migrate-pak-to-uvr into main 2026-07-31 12:19:27 +00:00
Owner

bincraft dropped pak in favour of uvr (5.0.x, "Dependencies and their system requirements are now installed with uvr instead of pak during build_binary_package()"), so the pipelines, helper scripts and images in this repo move with it.

Approach

uvr is project-scoped in a way pak is not: uvr add refuses to run outside a project and always installs into .uvr/library/, and only uvr sync honours --library. So there is no one-line pak::pak(...) equivalent. local/uvr-install.sh encapsulates the dance — bootstrap a pinned uvr, mint a throwaway project under TMPDIR, uvr add --no-install, then uvr sync --library <target>. Keeping the project outside the checkout also keeps uvr init's .Rprofile from hijacking .libPaths() for every other R call in the pipeline.

This matches what bincraft itself does (uvr sync --install-system-deps --library <lib>), and bincraft requires uvr on PATH, which the bootstrap provides: every pipeline that calls bincraft:: runs install-bincraft.R (and therefore the bootstrap) first.

Changes

File Change
local/uvr-install.sh New. The single replacement for pak::pak(...). Bootstraps uvr v0.4.4, resolves the R interpreter from UVR_R_BIN/R_VERSION/PATH, pins the manifest to that R's exact version, and syncs into UVR_TARGET_LIB/R_LIBS_USER.
local/install-bincraft.R Installs forgejo::codefloe.com/rpkgs/bincraft@<tag> instead of a git:: URL; keeps the git ls-remote tag resolution. Exports UVR_R_BIN/UVR_TARGET_LIB from R.home()/.libPaths()[1] so the per-R-minor passes target their own R and library.
.crow/auto-apply-patches.yaml, .crow/weekly-patch-proposals.yaml, .crow/weekly-audit-missing.yaml, .crow/weekly-rebuild-missing.yaml, .crow/build-all-versions-install-deps.yaml pak::pak(...)UVR_R_BIN=/opt/R/$R_VERSION/bin/R local/uvr-install.sh .... The explicit UVR_R_BIN matters in build-all-versions-install-deps.yaml, which has no R_VERSION in its step environment.
.crow/build-all-versions.yaml, .crow/process-updates.yaml, .crow/weekly-rebuild-missing.yaml R_PKG_CACHE_DIRUVR_CACHE_DIR + UVR_PACKAGES_DIR on the same /mnt/cache volume, preserving the amd64-off/arm64-on split. Drops the rm -rf .../pkgcache/_metadata/... cleanup.
local/r-minor-helpers.R, local/build-all.R, local/tests/test-trim-pkgcache.R Removes trim_pkgcache_metadata(), its every-25-packages call and its tests. uvr's cache does not mint a fresh ~70 MB snapshot per PACKAGES change.
.crow/build-all-versions-install-deps.yaml Drops pak::sysreqs_db_update(); uvr resolves sysreqs from its vendored r-system-requirements rules via --install-system-deps.
docker/Containerfile-shiny-app Bootstraps uvr and drives both dependency installs through one uvr project with UVR_LIBRARY pointed at the image's R library.
docker/build-one.Dockerfile Ships uvr-install.sh at /work/local/ so install-bincraft.R finds it.
docker/reprex/alpine.sh Replaces pak::local_install_deps() with DESCRIPTION parsing + uvr add.
local/test-package-loading.R Installs via the helper instead of pak::pkg_install().
README.md Documents uvr for sysreq inference, archived-version installs and cache clearing.
renovate.json Tracks the UVR_PIN in uvr-install.sh via github-releases.

Behaviour notes

  • weekly-audit-missing now pins bincraft to its latest release (second commit). It previously installed from the default branch — the pre-uvr pak::pak("git::...") call did too — so an unreleased commit could change what the weekly audit reported. It now uses install-bincraft.R like every other pipeline.
  • The uvr pin is repo-wide. bincraft resolves uvr from PATH and pins no version of its own, so UVR_PIN in uvr-install.sh governs the whole pipeline.
  • Persistent caches now also benefit bincraft, which reads UVR_CACHE_DIR/UVR_PACKAGES_DIR from the inherited pipeline environment.
  • uvr sync will not prune the shared library. Pruning is disabled whenever --library is passed (do_prune = prune && library_override.is_none()), so /mnt/cache/R-pkgs keeps bincraft and its dependencies. The wipe-on-ABI-mismatch path is not similarly guarded, which is why the helper pins the manifest to the active R's exact version.
  • plans/ and specs/ are untouched — they are dated records of decisions made in June 2026 and describe bincraft's then-pak-based internals; rewriting them would misstate history.

Verification

shellcheck, all pre-commit hooks (on this commit's file range) and the local/tests/ suite (100 assertions) pass.

Not yet exercised in CI: the build-env images do not ship uvr, so the per-step curl install.sh bootstrap is untested against a real image. Worth a manual build-all-versions-install-deps run before merging.

`bincraft` dropped pak in favour of uvr (5.0.x, "Dependencies and their system requirements are now installed with `uvr` instead of pak during `build_binary_package()`"), so the pipelines, helper scripts and images in this repo move with it. ## Approach uvr is project-scoped in a way pak is not: `uvr add` refuses to run outside a project and always installs into `.uvr/library/`, and only `uvr sync` honours `--library`. So there is no one-line `pak::pak(...)` equivalent. `local/uvr-install.sh` encapsulates the dance — bootstrap a pinned uvr, mint a throwaway project under `TMPDIR`, `uvr add --no-install`, then `uvr sync --library <target>`. Keeping the project outside the checkout also keeps `uvr init`'s `.Rprofile` from hijacking `.libPaths()` for every other R call in the pipeline. This matches what bincraft itself does (`uvr sync --install-system-deps --library <lib>`), and bincraft requires `uvr` on `PATH`, which the bootstrap provides: every pipeline that calls `bincraft::` runs `install-bincraft.R` (and therefore the bootstrap) first. ## Changes | File | Change | | --- | --- | | `local/uvr-install.sh` | **New.** The single replacement for `pak::pak(...)`. Bootstraps uvr `v0.4.4`, resolves the R interpreter from `UVR_R_BIN`/`R_VERSION`/`PATH`, pins the manifest to that R's exact version, and syncs into `UVR_TARGET_LIB`/`R_LIBS_USER`. | | `local/install-bincraft.R` | Installs `forgejo::codefloe.com/rpkgs/bincraft@<tag>` instead of a `git::` URL; keeps the `git ls-remote` tag resolution. Exports `UVR_R_BIN`/`UVR_TARGET_LIB` from `R.home()`/`.libPaths()[1]` so the per-R-minor passes target their own R and library. | | `.crow/auto-apply-patches.yaml`, `.crow/weekly-patch-proposals.yaml`, `.crow/weekly-audit-missing.yaml`, `.crow/weekly-rebuild-missing.yaml`, `.crow/build-all-versions-install-deps.yaml` | `pak::pak(...)` → `UVR_R_BIN=/opt/R/$R_VERSION/bin/R local/uvr-install.sh ...`. The explicit `UVR_R_BIN` matters in `build-all-versions-install-deps.yaml`, which has no `R_VERSION` in its step environment. | | `.crow/build-all-versions.yaml`, `.crow/process-updates.yaml`, `.crow/weekly-rebuild-missing.yaml` | `R_PKG_CACHE_DIR` → `UVR_CACHE_DIR` + `UVR_PACKAGES_DIR` on the same `/mnt/cache` volume, preserving the amd64-off/arm64-on split. Drops the `rm -rf .../pkgcache/_metadata/...` cleanup. | | `local/r-minor-helpers.R`, `local/build-all.R`, `local/tests/test-trim-pkgcache.R` | Removes `trim_pkgcache_metadata()`, its every-25-packages call and its tests. uvr's cache does not mint a fresh ~70 MB snapshot per `PACKAGES` change. | | `.crow/build-all-versions-install-deps.yaml` | Drops `pak::sysreqs_db_update()`; uvr resolves sysreqs from its vendored `r-system-requirements` rules via `--install-system-deps`. | | `docker/Containerfile-shiny-app` | Bootstraps uvr and drives both dependency installs through one uvr project with `UVR_LIBRARY` pointed at the image's R library. | | `docker/build-one.Dockerfile` | Ships `uvr-install.sh` at `/work/local/` so `install-bincraft.R` finds it. | | `docker/reprex/alpine.sh` | Replaces `pak::local_install_deps()` with DESCRIPTION parsing + `uvr add`. | | `local/test-package-loading.R` | Installs via the helper instead of `pak::pkg_install()`. | | `README.md` | Documents uvr for sysreq inference, archived-version installs and cache clearing. | | `renovate.json` | Tracks the `UVR_PIN` in `uvr-install.sh` via `github-releases`. | ## Behaviour notes - **`weekly-audit-missing` now pins bincraft to its latest release** (second commit). It previously installed from the default branch — the pre-uvr `pak::pak("git::...")` call did too — so an unreleased commit could change what the weekly audit reported. It now uses `install-bincraft.R` like every other pipeline. - **The uvr pin is repo-wide.** bincraft resolves `uvr` from `PATH` and pins no version of its own, so `UVR_PIN` in `uvr-install.sh` governs the whole pipeline. - **Persistent caches now also benefit bincraft**, which reads `UVR_CACHE_DIR`/`UVR_PACKAGES_DIR` from the inherited pipeline environment. - **`uvr sync` will not prune the shared library.** Pruning is disabled whenever `--library` is passed (`do_prune = prune && library_override.is_none()`), so `/mnt/cache/R-pkgs` keeps bincraft and its dependencies. The wipe-on-ABI-mismatch path is *not* similarly guarded, which is why the helper pins the manifest to the active R's exact version. - **`plans/` and `specs/` are untouched** — they are dated records of decisions made in June 2026 and describe bincraft's then-pak-based internals; rewriting them would misstate history. ## Verification `shellcheck`, all pre-commit hooks (on this commit's file range) and the `local/tests/` suite (100 assertions) pass. Not yet exercised in CI: the build-env images do not ship `uvr`, so the per-step `curl install.sh` bootstrap is untested against a real image. Worth a manual `build-all-versions-install-deps` run before merging.
bincraft dropped pak in favour of uvr, so the pipelines, helper scripts
and images in this repo move with it.

- add local/uvr-install.sh as the single replacement for pak::pak(); it
  bootstraps a pinned uvr, mints a throwaway project under TMPDIR and
  runs `uvr add --no-install` + `uvr sync --library`, because `uvr add`
  refuses to run outside a project and only `sync` honours --library
- install bincraft via its Forgejo spec (forgejo::codefloe.com/rpkgs/
  bincraft@<tag>) instead of a git:: URL, keeping the git ls-remote tag
  resolution
- pass UVR_R_BIN/UVR_TARGET_LIB from install-bincraft.R so the
  per-R-minor passes target their own R and library
- replace R_PKG_CACHE_DIR with UVR_CACHE_DIR/UVR_PACKAGES_DIR on the
  persistent volume, preserving the amd64-off/arm64-on split
- drop trim_pkgcache_metadata() and its test; uvr's cache does not grow
  the way pkgcache's _metadata dir did
- let uvr install system requirements from its vendored
  r-system-requirements rules, replacing pak::sysreqs_db_update()
- migrate the shiny app image, the alpine reprex and the CRAN loading
  test; ship uvr-install.sh in the build-one image
- track the uvr pin with renovate
The audit step installed bincraft from the default branch, which the
pre-uvr pak call also did. Every other pipeline resolves the newest
vX.Y.Z tag via install-bincraft.R; do the same here so an unreleased
commit cannot change what the weekly audit reports.
pat-s merged commit ee15c50f53 into main 2026-07-31 12:19:27 +00:00
pat-s deleted branch t3code/migrate-pak-to-uvr 2026-07-31 12:19:27 +00:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
devxy/build-cran-binaries!147
No description provided.