RStudio Connect, Packrat и пользовательские пакеты в локальных репозиториях
Мы недавно получили RStudio Connect в моем офисе. Для нашей работы мы создали пользовательские пакеты, которые мы обновили между собой, открыв проект и выполнив сборку + перезагрузка.
Я понимаю, что единственный способ заставить наши пользовательские пакеты работать в приложениях с RSConnect - это запустить локальное репо и настроить наш options(repos)
включить это.
В настоящее время у меня есть следующее:
library(drat)
RepoAddress <- "C:/<RepoPath>" # High level path
drat::insertPackage(<sourcePackagePath>, repodir = RepoAddress)
# Add this new repo to Rs knowledge of repos.
options(repos = c(options("repos")$repos,LocalCurrent = paste0("file:",RepoAddress)))
# Install <PackageName> from the local repo :)
install.packages("<PackageName>")
В настоящее время это работает хорошо, и я могу установить свой собственный пакет из локального репозитория. Это указывает на то, что локальное репо настроено правильно.
В качестве дополнительного, я изменил DESCRIPTION
файл, чтобы иметь дополнительную строку, говорящую repository:LocalCurrent
,
Однако, когда я пытаюсь развернуть приложение Shiny или Rmd, на которое ссылается, при развертывании я получаю следующую ошибку:
Error in findLocalRepoForPkg(pkg, repos, fatal = fatal) :
No package '<PackageName> 'found in local repositories specified
Я так понимаю это проблема с packrat
не удается найти мои локальные репозитории во время процесса развертывания (я полагаю, на этапе, когда он использует packrat::snapshot()
). Это сбивает с толку, так как я бы подумал packrat
будет использовать мой option("repos")
репо, похожие на install.packages
, Если я буду следовать через функции, я вижу, что конкретная точка отказа packrat:::findLocalRepoForPkg("<PackageName", repos = packrat::get_opts("local.repos"))
, который не удается даже после того, как я определю packrat::set_opts("local.repos" = c(CurrentRepo2 = paste0("file:",RepoAddress)))
Если я сверлю в packrat:::findLocalRepoForPkg
, он терпит неудачу, потому что не может найти файл / папку с именем: "C://". Я бы подумал, что это гарантированно потерпит неудачу, потому что репозитории следуют структуре C://bin/windows/contrib/3.3/. Ни в коем случае репо не будет иметь структуру, которую ищет?
Я думаю, что эта последняя часть показывает, что я чего-то недопонимаю. Любое руководство по настройке моего репо так packrat
могу понять это было бы здорово.
2 ответа
Всегда нужно проверять, какие опции RStudio connect поддерживает на данный момент:https://docs.rstudio.com/connect/admin/r/package-management/#private-packages
Лично мне не нравятся все варианты включения локальных / частных пакетов, так как это лишает вас хорошей легкой цели для развертывания блестящих приложений. Во многих случаях я не могу просто создать локальные репозитории в организации, потому что у меня нет на это разрешения. Также неудобно, что мне приходится писать в службу поддержки по электронной почте, чтобы они вручную устанавливали новые пакеты. В целом я считаю, что RS connect - отличный продукт, потому что он прост, но когда дело доходит до локальных пакетов, это действительно не так.
Я нашел хорошую альтернативу / Взломайте официальные рекомендации Rstudio. Я предполагаю, что это также будет работать с shinyapps.io, но я не пробовал. Решение выглядит так:
добавить в global.R, если (!require(local_package)) devtools::load_all("./local_package")
Напишите сценарий, который копирует все ваши исходные файлы, так что вы получите shinyapp с исходным каталогом для локального пакета внутри, вы можете вызвать каталог для
./inst/shinyconnect/
или какой-либо и локальный пакет будет скопирован в./inst/shinyconnect/local_package
манифест.добавить скрипт
./shinyconnect/packrat_sees_these_dependencies.R
в блестящую папку, это будет подхвачено packrat-manifestВзломайте rsconnet/packrat, чтобы игнорировать пакеты с конкретными именами при сборке
(1)
#start of global.R...
#load more packages for shiny
library(devtools) #need for load_all
library(shiny)
library(htmltools) #or what ever you need
#load already built local_package or for shiny connection pseudo-build on-the-fly and load
if(!require(local_package)) {
#if local_package here, just build on 2 sec with devtools::load_all()
if(file.exists("./DESCRIPTION")) load_all(".") #for local test on PC/Mac, where the shinyapp is inside the local_package
if(file.exists("./local_package/DESCRIPTION")) load_all("./local_package/") #for shiny conenct where local_package is inside shinyapp
}
library(local_package) #now local_package must load
(3) заставить скрипт загружать все зависимости вашего локального пакета. Пакрат увидит это. Фактически сценарий никогда не будет выполнен. Поместите это в
./shinyconnect/packrat_sees_these_dependencies.R
#these codelines will be recognized by packrat and package will be added to manifest
library(randomForest)
library(MASS)
library(whateverpackageyouneed)
(4) Во время развертывания генератор манифеста (packrat) игнорирует существование любого именованного local_package. Это опция в packrat, но rsconnect не предоставляет эту опцию. Хакерство заключается в загрузке rsconnect в память и изменении под-под-подфункции
performPackratSnapshot()
чтобы позволить это. В приведенном ниже сценарии я делаю это и развертываю блестящее приложение.
library(rsconnect)
orig_fun = getFromNamespace("performPackratSnapshot", pos="package:rsconnect")
#packages you want include manually, and packrat to ignore
ignored_packages = c("local_package")
#highjack rsconnect
local({
assignInNamespace("performPackratSnapshot",value = function (bundleDir) {
owd <- getwd()
on.exit(setwd(owd), add = TRUE)
setwd(bundleDir)
srp <- packrat::opts$snapshot.recommended.packages()
packrat::opts$snapshot.recommended.packages(TRUE, persist = FALSE)
packrat::opts$ignored.packages(get("ignored_packages",envir = .GlobalEnv)) #ignoreing packages mentioned here
print("ignoring following packages")
print(get("ignored_packages",envir = .GlobalEnv))
on.exit(packrat::opts$snapshot.recommended.packages(srp,persist = FALSE), add = TRUE)
packages <- c("BiocManager", "BiocInstaller")
for (package in packages) {
if (length(find.package(package, quiet = TRUE))) {
requireNamespace(package, quietly = TRUE)
break
}
}
suppressMessages(packrat::.snapshotImpl(project = bundleDir,
snapshot.sources = FALSE, fallback.ok = TRUE, verbose = FALSE,
implicit.packrat.dependency = FALSE))
TRUE
},
pos = "package:rsconnect"
)},
envir = as.environment("package:rsconnect")
)
new_fun = getFromNamespace("performPackratSnapshot", pos="package:rsconnect")
rsconnect::deployApp(appDir="./inst/shinyconnect/",appName ="shinyapp_name",logLevel = "verbose",forceUpdate = TRUE)
Проблема в номенклатуре.
Я создал репо в смысле CRAN. Работает нормально и нормально. когда packrat
ссылки на local repo
, это относится к местному репозиторию в стиле git.
Это решает, почему findlocalrepoforpkg не выглядит так, как будто он будет работать - он предназначен для работы с другим типом репо.
Не стесняйтесь также связаться с support@rstudio.com
Я считаю, что локальный путь к коду пакета запускается в пакрате из-за отсутствия Repository: value
строка в файле описания пакета. Вы упомянули, что добавили эту строку, не могли бы вы попробовать версию с учетом регистра?
Тем не менее, RStudio Connect не сможет установить пакет из RepoAddress
как вы указали (жестко запрограммировано в общей папке Windows). Мы рекомендуем размещать репо через https с сервера, к которому есть доступ как к среде разработки, так и к RStudio Connect. Чтобы упростить настройку репо такого типа, мы только что выпустили RStudio Package Manager, который вы (и ИТ-специалисты) можете найти убедительной альтернативой ручному управлению выпусками ваших внутренних пакетов с помощью drat.