2

我们最近在我的办公室安装了 RStudio Connect。对于我们的工作,我们制作了自定义包,我们通过打开项目和构建+重新加载在自己之间进行了更新。

我知道我可以让我们的自定义包在带有 RSConnect 的应用程序中工作的唯一方法是建立一个本地 repo 并设置我们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>")

目前这很好用,我可以从本地 repo 安装我的自定义包。这向我表明本地存储库已正确设置。

另外,我已将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://”的文件/文件夹。我原以为这肯定会失败,因为 repos 遵循 C://bin/windows/contrib/3.3/ 结构。回购协议在任何时候都不会具有它正在寻找的结构吗?

我认为这最后一部分表明我在本质上误解了一些东西。任何有关配置我的 repo 的指导packrat都可以理解它会很棒。

4

3 回答 3

3

应始终检查 RStudio connect 目前支持哪些选项: https ://docs.rstudio.com/connect/admin/r/package-management/#private-packages

就我个人而言,我不喜欢包含本地/私有包的所有选项,因为它违背了部署闪亮应用程序的简单目标的目的。在许多情况下,我不能只在组织中设置本地存储库,因为我没有权限。我必须给 IT 支持发送电子邮件以让他们手动安装新软件包也很不方便。总的来说,我认为 RS connect 是一个很棒的产品,因为它很简单,但是当涉及到本地包时,它真的不是。

我找到了 Rstudio 官方推荐的一个不错的替代方案/Hack。我想thise也可以与shinyapps.io一起使用,但我还没有尝试过。解决方案如下:

  1. 添加到 global.R if(!require(local_package) ) devtools::load_all("./local_package")

  2. 编写一个复制所有源文件的脚本,这样您就可以得到一个带有本地包源目录的闪亮应用程序,您可以调用该目录,./inst/shinyconnect/或者将本地包复制到./inst/shinyconnect/local_package 清单中。

  3. 将脚本添加./shinyconnect/packrat_sees_these_dependencies.R到闪亮文件夹,这将由 packrat-m​​anifest 拾取

  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) make script 加载你本地包的所有依赖。Packrat 会看到这一点。该脚本永远不会被实际执行。把它放在./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 加载到内存并修改 sub-sub-sub-functionperformPackratSnapshot()以允许这样做。在下面的脚本中,我这样做并部署了一个闪亮的应用程序。

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)
于 2020-09-29T13:15:17.863 回答
0

问题是命名法之一。

我已经建立了 CRAN 意义上的回购协议。它工作正常并且没问题。当packrat引用 alocal repo时,它指的是本地 git 样式的 repo。

这解决了为什么 findlocalrepoforpkg 看起来不起作用 - 它旨在与不同类型的 repo 一起使用。

于 2018-10-26T11:09:15.173 回答
0

也请随时联系 support@rstudio.com

我相信由于包的描述文件中缺少Repository: value行,因此在 packrat 中触发了本地包代码路径。您提到您添加了这一行,您可以尝试区分大小写的版本吗?

也就是说,RStudio Connect 将无法RepoAddress按照您指定的方式安装包(硬编码在 Windows 共享上)。我们建议通过 https 从您的开发环境和 RStudio Connect 都可以访问的服务器托管您的存储库。为了使这种类型的 repo 设置更容易,我们刚刚发布了RStudio Package Manager,您(和 IT!)可能会找到一个引人注目的替代方案,而不是通过 drat 手动管理内部包的发布。

于 2018-10-26T16:25:36.610 回答