我目前正在为我们公司开发的R软件包进行持续集成设置。我们为每个R包都有一个Jenkins项目,每个项目都有一个相应的库。
我已经定义了一个逻辑,它将包的所有依赖项安装到项目库中。现在我想定义一个基本上运行的检查阶段
devtools::check("${PROJECT_DIR}/pkg")
但只使用项目库进行依赖。我尝试以下列方式使用callr
包。
callr::r(
function(...) {
devtools::check(...)
),
args = list("${PROJECT_DIR}/pkg"),
libpath = "${PROJECT_DIR}/lib"
)
但是,检查过程仍然能够找到未安装在libpath
中的软件包。有没有办法确保在构建阶段只使用"${PROJECT_DIR}/lib"
?
到目前为止,我已经尝试了以下无济于事
callr()
与libpath
论点withr::with_libpaths
与new
论点devtools::check
和R CMD BUILD
中的文档以获取适当的参数.libPaths("${JOB_DIR}/lib")
这是一个解释callr
的意外行为的rex。我预计第3行会出错。
find.package("ggplot2", .libPaths()[1])
#> Error in find.package("ggplot2", .libPaths()[1]): there is no package called 'ggplot2'
callr::r(function() { ggplot2::vars() }, libpath = .libPaths()[1])
#> named list()
find.package("ggplot2", .libPaths()[2])
#> [1] "/data/R/3.5.3/lib/R/library/ggplot2"
callr::r(function() { ggplot2::vars() }, libpath = .libPaths()[2])
#> named list()
根据qazxsw poi,有一种方法可以通过qazxsw poi实现这一目标。如果有更合适的解决方案,我很乐意听到。
this question
我在这里遇到的问题是双重的
base::assign
的内部改变,可以打破任何时间callr::r(function() {
assign(".lib.loc", .libPaths()[1], envir = environment(.libPaths))
ggplot2::vars()
})
#> Error in loadNamespace(name): there is no package called ‘ggplot2’
和.libPaths()
(.Library
的内部),以确保.Library.site
受到适当的影响。这可能稍微偏离主题,但您是否考虑过将.libPaths()
用于此用例?
您可以在devtools::check
中定义docker,它将为每个运行的CI作业定义自定义图像。使用Jenkins中的Dockerfile
将软件包安装到docker容器中。然后,当CI完成时,该容器被抛出。
使用此方法,您无需担心在运行CI时自己手动安装软件包,也不必担心不同软件包之间存在冲突的命名空间。
这肯定有更高的启动成本,但我认为从长远来看,你会发现测试你的R套件是值得的。资料来源:我还在工作中测试内部R包。
样本Jenkinsfile
devtools::install()
然后你在Dockerfile
中引用这个FROM docker.io/rocker/r-base
USER root
# Install packages needed for package development
RUN R -e 'install.packages(c("devtools", "rmarkdown", "testthat", "roxygen2"))'
来安装,测试和检查包(下面的管道示例)
Dockerfile