Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 31 additions & 6 deletions .github/workflows/ci-benchmark.yml
Original file line number Diff line number Diff line change
Expand Up @@ -84,18 +84,43 @@ jobs:
with:
use-public-rspm: true

# R dependencies via renv lockfile (issue #306, B1) — mirrors
# quarto-publish.yml: setup-renv keys its cache on the renv.lock
# hash; a changed lockfile only pays the delta.
- name: Install system dependencies
run: |
sudo apt-get update -y
sudo apt-get install -y libcurl4-openssl-dev

- name: Drop cached babelquarto before dependency install
run: Rscript -e 'if (requireNamespace("babelquarto", quietly = TRUE)) remove.packages("babelquarto")'
sudo apt-get install -y \
libcurl4-openssl-dev \
libudunits2-dev \
libglpk-dev \
librsvg2-dev

# pak derives the system requirements of the full dependency closure
# from DESCRIPTION — the same job PKG_SYSREQS=true used to do inside
# setup-r-dependencies. This MUST run before setup-renv: renv
# load-tests every package during restore, so missing system
# libraries (e.g. librsvg behind rsvg) would abort it. pak installs
# as a PPM binary in seconds; pkg_sysreqs() only returns the install
# commands (it never installs), so run them through a privileged
# shell here. The explicit apt line above covers the libraries
# known to be needed; this catches anything else in the closure.
- name: Install system requirements for locked packages
run: |
Rscript -e 'if (!requireNamespace("pak", quietly = TRUE)) install.packages("pak")'
SCRIPTS=$(Rscript -e 'cat(pak::pkg_sysreqs("deps::.")$install_scripts, sep = "\n")')
if [ -n "$SCRIPTS" ]; then
echo "$SCRIPTS" | sudo bash
else
echo "No additional system requirements needed"
fi

- uses: r-lib/actions/setup-r-dependencies@v2
- uses: r-lib/actions/setup-renv@v2
env:
PKG_SYSREQS: "true"
RENV_CONFIG_SANDBOX_ENABLED: false


# Mark AFTER setup-renv + sysreqs so r_deps measures the new pipeline.
- name: Mark phase — R dependencies done
run: echo "r_deps=$(date +%s)" >> /tmp/benchmark-clock

Expand Down
67 changes: 61 additions & 6 deletions .github/workflows/quarto-publish-update-cache.yml
Original file line number Diff line number Diff line change
Expand Up @@ -96,14 +96,47 @@ jobs:
with:
use-public-rspm: true

# See quarto-publish.yml: ensure a repinned babelquarto is actually
# reinstalled instead of reused from the restored package library.
- name: Drop cached babelquarto before dependency install
run: Rscript -e 'if (requireNamespace("babelquarto", quietly = TRUE)) remove.packages("babelquarto")'
# ── R dependencies via renv (issue #306, B1) ─────────────
# See quarto-publish.yml for the full rationale: renv.lock pins the
# exact versions resolved from DESCRIPTION, setup-renv keys its
# package cache on the lockfile hash, and a changed lockfile only
# pays the delta thanks to the restore-keys prefix. A repinned
# GitHub package (e.g. our babelquarto fork) therefore takes effect
# without any manual cache-busting step.
- name: Install system dependencies
run: |
sudo apt-get update -y
sudo apt-get install -y \
libcurl4-openssl-dev \
libudunits2-dev \
libglpk-dev \
librsvg2-dev

# pak derives the system requirements of the full dependency closure
# from DESCRIPTION — the same job PKG_SYSREQS=true used to do inside
# setup-r-dependencies. This MUST run before setup-renv: renv
# load-tests every package during restore, so missing system
# libraries (e.g. librsvg behind rsvg) would abort it. pak installs
# as a PPM binary in seconds; pkg_sysreqs() only returns the install
# commands (it never installs), so run them through a privileged
# shell here. The explicit apt line above covers the libraries
# known to be needed; this catches anything else in the closure.
- name: Install system requirements for locked packages
run: |
Rscript -e 'if (!requireNamespace("pak", quietly = TRUE)) install.packages("pak")'
SCRIPTS=$(Rscript -e 'cat(pak::pkg_sysreqs("deps::.")$install_scripts, sep = "\n")')
if [ -n "$SCRIPTS" ]; then
echo "$SCRIPTS" | sudo bash
else
echo "No additional system requirements needed"
fi

- uses: r-lib/actions/setup-r-dependencies@v2
- uses: r-lib/actions/setup-renv@v2
env:
PKG_SYSREQS: "true"
# See quarto-publish.yml: renv's sandbox doubles install time on
# ephemeral runners for no benefit.
RENV_CONFIG_SANDBOX_ENABLED: false


# ── Python Setup ─────────────────────────────────────────
- name: Set up Python
Expand Down Expand Up @@ -189,6 +222,28 @@ jobs:
Rscript update-dependencies.R
python manage-dependencies.py --update

# The scan above may append QMD-discovered install-call packages to
# DESCRIPTION that are newer than renv.lock; delta-install just the
# difference before rendering. See quarto-publish.yml for detail.
- name: Install scan-added dependencies (delta)
run: |
Rscript - <<'RS'
dcf <- read.dcf("DESCRIPTION")
imports <- if ("Imports" %in% colnames(dcf)) {
x <- trimws(strsplit(dcf[1, "Imports"], ",")[[1]])
gsub("\\(.*$", "", x)
} else character(0)
imports <- setdiff(imports[imports != "" & imports != "R"], "R")
missing <- imports[!vapply(imports, function(p)
requireNamespace(p, quietly = TRUE), logical(1))]
if (length(missing) == 0) {
message("All Imports loadable - no delta install needed.")
} else {
message("Delta-installing: ", paste(missing, collapse = ", "))
pak::pak(missing)
}
RS

- name: Commit updated dependency files
run: |
git config --local user.name "$GITHUB_ACTOR"
Expand Down
81 changes: 72 additions & 9 deletions .github/workflows/quarto-publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@
# ║ pushes cancel stale in-progress builds. ║
# ║ 5. RESOURCE CONSERVATION: Failed builds still save their freeze ║
# ║ progress, so the next run picks up where it left off. ║
# ║ 6. RENV LOCKFILE INSTALLS (issue #306, B1): R dependencies come ║
# ║ from renv.lock via setup-renv, cache keyed on the lockfile ║
# ║ hash — an unchanged lockfile restores in minutes instead of a ║
# ║ ~26 min pak resolution + install. ║
# ╚══════════════════════════════════════════════════════════════════════╝

on:
Expand Down Expand Up @@ -183,20 +187,51 @@ jobs:
with:
use-public-rspm: true

# ── R dependencies via renv (issue #306, B1) ─────────────
# renv.lock pins the exact versions resolved from DESCRIPTION by
# generate-renv-lock.yml, and setup-renv keys its package cache on
# the lockfile hash: an unchanged lockfile restores the whole
# library in minutes instead of re-resolving and installing ~650
# packages (~26 min). When the lockfile changes, the restore-keys
# prefix still restores the previous cache and renv::restore()
# installs only the delta — which is also why a repinned GitHub
# package (e.g. our babelquarto fork) takes effect without any
# manual cache-busting step.
- name: Install system dependencies
run: |
sudo apt-get update -y
sudo apt-get install -y libcurl4-openssl-dev

# The restored R package library may carry a previously installed
# build of a GitHub-pinned package; without this, pak reuses the old
# binary and a new pin (e.g. our babelquarto fork) never takes effect.
- name: Drop cached babelquarto before dependency install
run: Rscript -e 'if (requireNamespace("babelquarto", quietly = TRUE)) remove.packages("babelquarto")'
sudo apt-get install -y \
libcurl4-openssl-dev \
libudunits2-dev \
libglpk-dev \
librsvg2-dev

# pak derives the system requirements of the full dependency closure
# from DESCRIPTION — the same job PKG_SYSREQS=true used to do inside
# setup-r-dependencies. This MUST run before setup-renv: renv
# load-tests every package during restore, so missing system
# libraries (e.g. librsvg behind rsvg) would abort it. pak installs
# as a PPM binary in seconds; pkg_sysreqs() only returns the install
# commands (it never installs), so run them through a privileged
# shell here. The explicit apt line above covers the libraries
# known to be needed; this catches anything else in the closure.
- name: Install system requirements for locked packages
run: |
Rscript -e 'if (!requireNamespace("pak", quietly = TRUE)) install.packages("pak")'
SCRIPTS=$(Rscript -e 'cat(pak::pkg_sysreqs("deps::.")$install_scripts, sep = "\n")')
if [ -n "$SCRIPTS" ]; then
echo "$SCRIPTS" | sudo bash
else
echo "No additional system requirements needed"
fi

- uses: r-lib/actions/setup-r-dependencies@v2
- uses: r-lib/actions/setup-renv@v2
env:
PKG_SYSREQS: "true"
# renv's install sandbox copies packages into a private library
# before promoting them; on ephemeral CI runners it doubles
# install time for no benefit, so switch it off.
RENV_CONFIG_SANDBOX_ENABLED: false


# ── Python Setup ─────────────────────────────────────────
- name: Set up Python
Expand Down Expand Up @@ -292,6 +327,34 @@ jobs:
Rscript update-dependencies.R
python manage-dependencies.py --update

# The scan above appends QMD-discovered install-call packages to
# DESCRIPTION, but those are newer than renv.lock, so renv::restore()
# did not install them. Delta-install just the difference against
# the lockfile before anything renders. No-op on a typical run.
- name: Install scan-added dependencies (delta)
run: |
Rscript - <<'RS'
dcf <- read.dcf("DESCRIPTION")
imports <- if ("Imports" %in% colnames(dcf)) {
x <- trimws(strsplit(dcf[1, "Imports"], ",")[[1]])
gsub("\\(.*$", "", x)
} else character(0)
remotes_field <- if ("Remotes" %in% colnames(dcf)) {
trimws(strsplit(dcf[1, "Remotes"], ",")[[1]])
} else character(0)
# Remote refs (user/repo) are handled by renv from the Remotes
# field of the packages renv restores, not installed directly.
imports <- setdiff(imports[imports != "" & imports != "R"], "R")
missing <- imports[!vapply(imports, function(p)
requireNamespace(p, quietly = TRUE), logical(1))]
if (length(missing) == 0) {
message("All Imports loadable - no delta install needed.")
} else {
message("Delta-installing: ", paste(missing, collapse = ", "))
pak::pak(missing)
}
RS

- name: Commit updated dependency files
if: github.event_name != 'pull_request'
run: |
Expand Down
Loading