简体   繁体   English

本地存储库中的 RStudio Connect、Packrat 和自定义包

[英]RStudio Connect, Packrat, and custom packages in local repos

We have recently got RStudio Connect in my office.我们最近在我的办公室安装了 RStudio Connect。 For our work, we have made custom packages, which we have updated amongst ourselves by opening the project and build+reloading.对于我们的工作,我们制作了自定义包,我们通过打开项目和构建+重新加载在我们自己之间进行了更新。

I understand the only way I can get our custom packages to work within apps with RSConnect is to get up a local repo and set our options(repos) to include this.我知道让我们的自定义包在使用 RSConnect 的应用程序中工作的唯一方法是建立一个本地存储库并设置我们的options(repos)以包含它。

Currently I have the following:目前我有以下几点:

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>")

Currently this works nicely and I can install my custom package from the local repo.目前这很好用,我可以从本地存储库安装我的自定义包。 This indicates to me that the local repo is set up correctly.这向我表明本地存储库已正确设置。

As an additional aside, I have changed the DESCRIPTION file to have an extra line saying repository:LocalCurrent .另外,我已将DESCRIPTION文件更改为有一个额外的行说repository:LocalCurrent

However when I try to deploy a Shiny app or Rmd which references , I get the following error on my deploy:但是,当我尝试部署引用 的 Shiny 应用程序或 Rmd 时,我的部署出现以下错误:

Error in findLocalRepoForPkg(pkg, repos, fatal = fatal) : 
  No package '<PackageName> 'found in local repositories specified

I understand this is a problem with packrat being unable to find my local repos during the deploy process (I believe at a stage where it uses packrat::snapshot() ).This is confusing since I would have thought packrat would use my option("repos") repos similar to install.packages .我知道这是packrat在部署过程中无法找到我的本地存储库的问题(我相信在它使用packrat::snapshot()的阶段)。这令人困惑,因为我本以为packrat会使用我的option("repos")类似于install.packages If I follow through the functions, I can see the particular point of failure is packrat:::findLocalRepoForPkg("<PackageName", repos = packrat::get_opts("local.repos")) , which fails even after I define packrat::set_opts("local.repos" = c(CurrentRepo2 = paste0("file:",RepoAddress)))如果我按照这些函数进行操作,我可以看到特定的失败点是packrat:::findLocalRepoForPkg("<PackageName", repos = packrat::get_opts("local.repos")) ,即使在我定义了packrat::set_opts("local.repos" = c(CurrentRepo2 = paste0("file:",RepoAddress)))之后它也会失败packrat::set_opts("local.repos" = c(CurrentRepo2 = paste0("file:",RepoAddress)))

If I drill into packrat:::findLocalRepoForPkg , it fails because it can't find a file/folder called: "C://".如果我深入研究packrat:::findLocalRepoForPkg ,它会失败,因为它找不到名为“C://”的文件/文件夹。 I would have thought this is guaranteed to fail, because repos follow the C://bin/windows/contrib/3.3/ structure.我原以为这肯定会失败,因为 repos 遵循 C://bin/windows/contrib/3.3/ 结构。 At no point would a repo have the structure it's looking for?在任何时候,repo 都不会具有它正在寻找的结构吗?

I think this last part is showing I'm materially misunderstanding something.我认为这最后一部分表明我对某些事情有重大误解。 Any guidance on configuring my repo so packrat can understand it would be great.任何有关配置我的 repo 以便packrat能够理解它的指导都会很棒。

One should always check what options RStudio connect supports at the moment: https://docs.rstudio.com/connect/admin/r/package-management/#private-packages应该始终检查 RStudio connect 目前支持哪些选项: https : //docs.rstudio.com/connect/admin/r/package-management/#private-packages

Personally I dislike all options for including local/private packages, as it defeats the purpose of having a nice easy target for deploying shiny apps.就我个人而言,我不喜欢包含本地/私有包的所有选项,因为它违背了为部署闪亮的应用程序提供一个很好的简单目标的目的。 In many cases, I can't just set up local repositories in the organization because, I do not have clearance for that.在许多情况下,我不能只在组织中设置本地存储库,因为我没有权限。 It is also inconvenient that I have to email IT-support to make them manually install new packages.我必须通过电子邮件向 IT 支持人员发送电子邮件以让他们手动安装新软件包,这也很不方便。 Overall I think RS connect is great product because it is simple, but when it comes to local packages it is really not.总的来说,我认为 RS connect 是一款很棒的产品,因为它很简单,但是当涉及到本地包时,它真的不是。

I found a nice alternative/Hack to Rstudio official recommendations.我找到了 Rstudio 官方推荐的一个不错的替代方案/Hack。 I suppose thise would also work with shinyapps.io, but I have not tried.我想这也适用于 Shinyapps.io,但我还没有尝试过。 The solution goes like:解决方案如下:

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

  2. Write a script that copies all your source files, such that you get a shinyapp with a source directory for a local package inside, you could call the directory for ./inst/shinyconnect/ or what ever and local package would be copied to ./inst/shinyconnect/local_package manifest.编写一个脚本来复制你所有的源文件,这样你就可以得到一个带有本地包的源目录的 Shinyapp,你可以调用./inst/shinyconnect/的目录,或者将本地包复制到./inst/shinyconnect/local_package清单。

  3. add script ./shinyconnect/packrat_sees_these_dependencies.R to shiny folder, this will be picked up by packrat-manifest将脚本./shinyconnect/packrat_sees_these_dependencies.R添加到闪亮的文件夹中,这将被 packrat-m​​anifest 获取

  4. Hack rsconnet/packrat to ignore specifically named packages when building在构建时破解 rsconnet/packrat 以忽略特定命名的包

(1) (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 loading all the dependencies of your local package. (3) make script 加载本地包的所有依赖项。 Packrat will see this. Packrat 会看到这一点。 The script will never be actually be executed.脚本永远不会被实际执行。 Place it at ./shinyconnect/packrat_sees_these_dependencies.R将它放在./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) During deployment, manifest generator (packrat) will ignore the existence of any named local_package. (4)在部署过程中,清单生成器 (packrat) 会忽略任何命名的 local_package 的存在。 This is an option in packrat, but rsconnect does not expose this option.这是 Packrat 中的一个选项,但 rsconnect 不公开此选项。 A hack is to load rsconnect to memory and and modify the sub-sub-sub-function performPackratSnapshot() to allow this.一个技巧是将 rsconnect 加载到内存并修改 sub-sub-sub-function performPackratSnapshot()以允许这样做。 In script below, I do that and deploy a shiny app.在下面的脚本中,我这样做并部署了一个闪亮的应用程序。

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)

The problem is one of nomenclature.问题是命名法之一。

I have set up a repo in the CRAN sense.我已经建立了一个 CRAN 意义上的回购。 It works fine and is OK.它工作正常并且没问题。 When packrat references a local repo , it is referring to a local git-style repo.packrat引用local repo ,它指的是本地 git 样式的 repo。

This solves why findlocalrepoforpkg doesn't look like it will work - it is designed to work with a different kind of repo.这解决了为什么 findlocalrepoforpkg 看起来不起作用 - 它旨在与不同类型的 repo 一起使用。

Feel free to also reach out to support@rstudio.com也可以随时联系 support@rstudio.com

I believe the local package code path is triggered in packrat because of the missing Repository: value line in the Description file of the package.我相信本地包代码路径是在 Packrat 中触发的,因为包的描述文件中缺少Repository: value行。 You mentioned you added this line, could you try the case-sensitive version?您提到您添加了这一行,您可以尝试区分大小写的版本吗?

That said, RStudio Connect will not be able to install the package from the RepoAddress as you've specified it (hardcoded on the Windows share).也就是说,RStudio Connect 将无法从您指定的RepoAddress安装包(硬编码在 Windows 共享上)。 We'd recommend hosting your repo over https from a server that both your Dev environment and RStudio Connect have access to.我们建议从您的开发环境和 RStudio Connect 都可以访问的服务器通过 https 托管您的存储库。 To make this type of repo setup much easier we just released RStudio Package Manager which you (and IT!) may find a compelling alternative to manually managing releases of your internal packages via drat.为了使这种类型的 repo 设置更容易,我们刚刚发布了RStudio 包管理器,您(和 IT!)可能会找到一个引人注目的替代方案,通过 drat 手动管理您的内部包的发布。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM