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
1 change: 1 addition & 0 deletions .Rbuildignore
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,4 @@ rsconnect/
^\.claude$
^\.gitattributes$
^LICENSE\.md$
^dev$
2 changes: 1 addition & 1 deletion DESCRIPTION
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
Type: Package
Package: audit.connect
Title: Posit Connect Health Check
Version: 0.8.14
Version: 0.8.15
Authors@R:
person("Jumping", "Rivers", , "info@jumpingrivers.com", role = c("aut", "cre"))
Description: Posit Connect Health Check. Deploys various content types to
Expand Down
7 changes: 7 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
# audit.connect 0.8.15

## Bug fixes and minor improvements

* `dev/update_manifests.R` regenerates every plumber manifest in one call, under R 4.4.3 with packages built from CRAN source.
* The plumber manifests list only `plumber.R` and no longer pin R `~=4.4.0`.

# audit.connect 0.8.14

## Bug fixes and minor improvements
Expand Down
15 changes: 15 additions & 0 deletions README.Rmd
Original file line number Diff line number Diff line change
Expand Up @@ -149,3 +149,18 @@ are skipped unless `AUDIT_CONNECT_LIVE` is `true`:
Sys.setenv(AUDIT_CONNECT_LIVE = "true")
devtools::test()
```

## Updating the manifests

The plumber test bundles in `inst/extdata/` each ship a `manifest.json`. After changing a
bundle, or to pick up newer package versions, regenerate them all at once:

```r
source("dev/update_manifests.R")
update_manifests()
```

This runs `rsconnect::writeManifest()` under the R in `/opt/R/4.4.3`, because the manifest
records that R version and Connect needs a matching one. Pass `r_version` to use another.
Packages are built from CRAN source in an empty library, so the manifests never point at
binaries for a different OS. Expect it to take several minutes.
15 changes: 15 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -144,3 +144,18 @@ are skipped unless `AUDIT_CONNECT_LIVE` is `true`:
Sys.setenv(AUDIT_CONNECT_LIVE = "true")
devtools::test()
```

## Updating the manifests

The plumber test bundles in `inst/extdata/` each ship a `manifest.json`. After changing a
bundle, or to pick up newer package versions, regenerate them all at once:

```r
source("dev/update_manifests.R")
update_manifests()
```

This runs `rsconnect::writeManifest()` under the R in `/opt/R/4.4.3`, because the manifest
records that R version and Connect needs a matching one. Pass `r_version` to use another.
Packages are built from CRAN source in an empty library, so the manifests never point at
binaries for a different OS. Expect it to take several minutes.
72 changes: 72 additions & 0 deletions dev/update_manifests.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
# Regenerate every manifest.json under inst/extdata. Run it from the package
# root; the README section "Updating the manifests" shows how.
#
# The manifests are written by an R installed at /opt/R/<r_version>, since
# writeManifest() records the R version it runs under, and Connect needs a
# matching R. Packages are installed from CRAN source into an empty library,
# so every manifest points at https://cloud.r-project.org and never at
# binaries built for another OS (see tests/testthat/test-manifests.R).
update_manifests = function(r_version = "4.4.3", path = ".") {
rscript = file.path("/opt/R", r_version, "bin", "Rscript")
if (!file.exists(rscript)) {
cli::cli_abort("Can't find {.file {rscript}}. Install R {r_version}, for example with rig.")
}
manifests = list.files(
file.path(path, "inst", "extdata"),
pattern = "^manifest\\.json$",
recursive = TRUE,
full.names = TRUE
)
app_dirs = normalizePath(dirname(manifests))
cli::cli_alert_info("Updating {length(app_dirs)} manifest{?s} with R {r_version}")

lib = tempfile("manifest-lib-")
dir.create(lib)
on.exit(unlink(lib, recursive = TRUE), add = TRUE)
script = tempfile(fileext = ".R")
on.exit(unlink(script), add = TRUE)
writeLines(
c(
paste("write_manifests =", paste(deparse(write_manifests), collapse = "\n")),
"write_manifests(commandArgs(trailingOnly = TRUE))"
),
script
)

# Point every library variable at the empty library, so nothing from the
# user or site library ends up in a manifest
env = c(
paste0("R_LIBS=", lib),
paste0("R_LIBS_USER=", lib),
paste0("R_LIBS_SITE=", lib),
"R_PROFILE_USER=/dev/null",
"R_ENVIRON_USER=/dev/null"
)
status = system2(rscript, c(shQuote(script), shQuote(app_dirs)), env = env)
if (status != 0) {
cli::cli_abort("Writing the manifests failed with status {status}.")
}
cli::cli_alert_success("Updated {.file {manifests}}")
invisible(manifests)
}

# Runs in the child R. Installs rsconnect and whatever the apps use, then
# writes a manifest that lists only the files in each app directory.
write_manifests = function(app_dirs) {
options(
repos = c(CRAN = "https://cloud.r-project.org"),
Ncpus = parallel::detectCores(),
# Otherwise the locale comes from whoever runs this
rsconnect.locale = "en_US"
)
utils::install.packages("rsconnect", type = "source", quiet = TRUE)
deps = unique(renv::dependencies(app_dirs, quiet = TRUE)$Package)
deps = setdiff(deps, rownames(utils::installed.packages()))
utils::install.packages(deps, type = "source", quiet = TRUE)

for (app_dir in app_dirs) {
app_files = setdiff(list.files(app_dir), "manifest.json")
rsconnect::writeManifest(appDir = app_dir, appFiles = app_files, quiet = TRUE)
message("Wrote ", file.path(app_dir, "manifest.json"))
}
}
23 changes: 0 additions & 23 deletions inst/extdata/README.qmd

This file was deleted.

Loading
Loading