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, но я не пробовал. Решение выглядит так:

  1. добавить в global.R, если (!require(local_package)) devtools::load_all("./local_package")

  2. Напишите сценарий, который копирует все ваши исходные файлы, так что вы получите shinyapp с исходным каталогом для локального пакета внутри, вы можете вызвать каталог для ./inst/shinyconnect/ или какой-либо и локальный пакет будет скопирован в ./inst/shinyconnect/local_packageманифест.

  3. добавить скрипт ./shinyconnect/packrat_sees_these_dependencies.R в блестящую папку, это будет подхвачено packrat-manifest

  4. Взломайте 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.

Другие вопросы по тегам