diff --git a/.Rbuildignore b/.Rbuildignore index 9e3b6db..f916c11 100644 --- a/.Rbuildignore +++ b/.Rbuildignore @@ -17,3 +17,6 @@ $run_dev.* ^\.Renviron$ ^\.Rprofile$ ^config\.yml$ +^build$ +^Dockerfile$ +^\.dockerignore$ diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..f52ee68 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,7 @@ +.RData +.Rhistory +.git +.gitignore +manifest.json +rsconnect/ +.Rproj.user diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..4f1d45c --- /dev/null +++ b/Dockerfile @@ -0,0 +1,20 @@ +FROM rocker/verse:4.4.1 +RUN apt-get update && apt-get install -y && rm -rf /var/lib/apt/lists/* +RUN mkdir -p /usr/local/lib/R/etc/ /usr/lib/R/etc/ +RUN echo "options(repos = c(CRAN = 'https://cran.rstudio.com/'), download.file.method = 'libcurl', Ncpus = 4)" | tee /usr/local/lib/R/etc/Rprofile.site | tee /usr/lib/R/etc/Rprofile.site +RUN R -e 'install.packages("remotes")' +RUN Rscript -e 'remotes::install_version("pkgload",upgrade="never", version = "1.3.4")' +RUN Rscript -e 'remotes::install_version("knitr",upgrade="never", version = "1.47")' +RUN Rscript -e 'remotes::install_version("shiny",upgrade="never", version = "1.8.1.1")' +RUN Rscript -e 'remotes::install_version("config",upgrade="never", version = "0.3.2")' +RUN Rscript -e 'remotes::install_version("testthat",upgrade="never", version = "3.2.1.1")' +RUN Rscript -e 'remotes::install_version("spelling",upgrade="never", version = "2.3.0")' +RUN Rscript -e 'remotes::install_version("rmarkdown",upgrade="never", version = "2.27")' +RUN Rscript -e 'remotes::install_version("golem",upgrade="never", version = "0.4.1")' +RUN mkdir /build_zone +ADD . /build_zone +WORKDIR /build_zone +RUN R -e 'remotes::install_local(upgrade="never")' +RUN rm -rf /build_zone +EXPOSE 80 +CMD R -e "options('shiny.port'=80,shiny.host='0.0.0.0');library(rshinycloudrun);rshinycloudrun::run_app()" diff --git a/build/.gitignore b/build/.gitignore new file mode 100644 index 0000000..b214053 --- /dev/null +++ b/build/.gitignore @@ -0,0 +1,8 @@ +* +!.gitignore +!Dockerfile +!Dockerfile_base +!README.md +!renv.lock.prod +!renv.lock +!compose.yml diff --git a/build/Dockerfile b/build/Dockerfile new file mode 100644 index 0000000..927a426 --- /dev/null +++ b/build/Dockerfile @@ -0,0 +1,8 @@ +FROM shinyexample_base +COPY renv.lock.prod renv.lock +RUN R -e 'renv::restore()' +COPY shinyexample_*.tar.gz /app.tar.gz +RUN R -e 'remotes::install_local("/app.tar.gz",upgrade="never")' +RUN rm /app.tar.gz +EXPOSE 80 +CMD R -e "options('shiny.port'=80,shiny.host='0.0.0.0');library(shinyexample);shinyexample::run_app()" diff --git a/build/Dockerfile_base b/build/Dockerfile_base new file mode 100644 index 0000000..3865690 --- /dev/null +++ b/build/Dockerfile_base @@ -0,0 +1,8 @@ +FROM rocker/r-ver:latest:4.4.1 +RUN apt-get update -y && apt-get install -y make zlib1g-dev git && rm -rf /var/lib/apt/lists/* +RUN mkdir -p /usr/local/lib/R/etc/ /usr/lib/R/etc/ +RUN echo "options(renv.config.pak.enabled = FALSE, repos = c(CRAN = 'https://cran.rstudio.com/'), download.file.method = 'libcurl', Ncpus = 4)" | tee /usr/local/lib/R/etc/Rprofile.site | tee /usr/lib/R/etc/Rprofile.site +RUN R -e 'install.packages("remotes")' +RUN R -e 'remotes::install_version("renv", version = "1.0.3")' +COPY renv.lock.prod renv.lock +RUN R -e 'renv::restore()' diff --git a/build/renv.lock.prod b/build/renv.lock.prod new file mode 100644 index 0000000..502f6e4 --- /dev/null +++ b/build/renv.lock.prod @@ -0,0 +1,554 @@ +{ + "R": { + "Version": "4.4.1", + "Repositories": [ + { + "Name": "CRAN", + "URL": "https://cran.rstudio.com" + } + ] + }, + "Packages": { + "R6": { + "Package": "R6", + "Version": "2.5.1", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R" + ], + "Hash": "470851b6d5d0ac559e9d01bb352b4021" + }, + "Rcpp": { + "Package": "Rcpp", + "Version": "1.0.12", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "methods", + "utils" + ], + "Hash": "5ea2700d21e038ace58269ecdbeb9ec0" + }, + "attempt": { + "Package": "attempt", + "Version": "0.3.1", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "rlang" + ], + "Hash": "d7421bb5dfeb2676b9e4a5a60c2fcfd2" + }, + "base64enc": { + "Package": "base64enc", + "Version": "0.1-3", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R" + ], + "Hash": "543776ae6848fde2f48ff3816d0628bc" + }, + "bslib": { + "Package": "bslib", + "Version": "0.7.0", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "base64enc", + "cachem", + "fastmap", + "grDevices", + "htmltools", + "jquerylib", + "jsonlite", + "lifecycle", + "memoise", + "mime", + "rlang", + "sass" + ], + "Hash": "8644cc53f43828f19133548195d7e59e" + }, + "cachem": { + "Package": "cachem", + "Version": "1.1.0", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "fastmap", + "rlang" + ], + "Hash": "cd9a672193789068eb5a2aad65a0dedf" + }, + "callr": { + "Package": "callr", + "Version": "3.7.6", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "R6", + "processx", + "utils" + ], + "Hash": "d7e13f49c19103ece9e58ad2d83a7354" + }, + "cli": { + "Package": "cli", + "Version": "3.6.2", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "utils" + ], + "Hash": "1216ac65ac55ec0058a6f75d7ca0fd52" + }, + "commonmark": { + "Package": "commonmark", + "Version": "1.9.1", + "Source": "Repository", + "Repository": "CRAN", + "Hash": "5d8225445acb167abf7797de48b2ee3c" + }, + "config": { + "Package": "config", + "Version": "0.3.2", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "yaml" + ], + "Hash": "8b7222e9d9eb5178eea545c0c4d33fc2" + }, + "crayon": { + "Package": "crayon", + "Version": "1.5.2", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "grDevices", + "methods", + "utils" + ], + "Hash": "e8a1e41acf02548751f45c718d55aa6a" + }, + "desc": { + "Package": "desc", + "Version": "1.4.3", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "R6", + "cli", + "utils" + ], + "Hash": "99b79fcbd6c4d1ce087f5c5c758b384f" + }, + "digest": { + "Package": "digest", + "Version": "0.6.35", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "utils" + ], + "Hash": "698ece7ba5a4fa4559e3d537e7ec3d31" + }, + "fastmap": { + "Package": "fastmap", + "Version": "1.2.0", + "Source": "Repository", + "Repository": "CRAN", + "Hash": "aa5e1cd11c2d15497494c5292d7ffcc8" + }, + "fontawesome": { + "Package": "fontawesome", + "Version": "0.5.2", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "htmltools", + "rlang" + ], + "Hash": "c2efdd5f0bcd1ea861c2d4e2a883a67d" + }, + "fs": { + "Package": "fs", + "Version": "1.6.4", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "methods" + ], + "Hash": "15aeb8c27f5ea5161f9f6a641fafd93a" + }, + "glue": { + "Package": "glue", + "Version": "1.7.0", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "methods" + ], + "Hash": "e0b3a53876554bd45879e596cdb10a52" + }, + "golem": { + "Package": "golem", + "Version": "0.4.1", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "attempt", + "config", + "here", + "htmltools", + "rlang", + "shiny", + "utils", + "yaml" + ], + "Hash": "dc12172dc35c6c80e18b430dc546fc24" + }, + "here": { + "Package": "here", + "Version": "1.0.1", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "rprojroot" + ], + "Hash": "24b224366f9c2e7534d2344d10d59211" + }, + "htmltools": { + "Package": "htmltools", + "Version": "0.5.8.1", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "base64enc", + "digest", + "fastmap", + "grDevices", + "rlang", + "utils" + ], + "Hash": "81d371a9cc60640e74e4ab6ac46dcedc" + }, + "httpuv": { + "Package": "httpuv", + "Version": "1.6.15", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "R6", + "Rcpp", + "later", + "promises", + "utils" + ], + "Hash": "d55aa087c47a63ead0f6fc10f8fa1ee0" + }, + "jquerylib": { + "Package": "jquerylib", + "Version": "0.1.4", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "htmltools" + ], + "Hash": "5aab57a3bd297eee1c1d862735972182" + }, + "jsonlite": { + "Package": "jsonlite", + "Version": "1.8.8", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "methods" + ], + "Hash": "e1b9c55281c5adc4dd113652d9e26768" + }, + "later": { + "Package": "later", + "Version": "1.3.2", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "Rcpp", + "rlang" + ], + "Hash": "a3e051d405326b8b0012377434c62b37" + }, + "lifecycle": { + "Package": "lifecycle", + "Version": "1.0.4", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "cli", + "glue", + "rlang" + ], + "Hash": "b8552d117e1b808b09a832f589b79035" + }, + "magrittr": { + "Package": "magrittr", + "Version": "2.0.3", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R" + ], + "Hash": "7ce2733a9826b3aeb1775d56fd305472" + }, + "memoise": { + "Package": "memoise", + "Version": "2.0.1", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "cachem", + "rlang" + ], + "Hash": "e2817ccf4a065c5d9d7f2cfbe7c1d78c" + }, + "mime": { + "Package": "mime", + "Version": "0.12", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "tools" + ], + "Hash": "18e9c28c1d3ca1560ce30658b22ce104" + }, + "pkgbuild": { + "Package": "pkgbuild", + "Version": "1.4.4", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "R6", + "callr", + "cli", + "desc", + "processx" + ], + "Hash": "a29e8e134a460a01e0ca67a4763c595b" + }, + "pkgload": { + "Package": "pkgload", + "Version": "1.3.4", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "cli", + "crayon", + "desc", + "fs", + "glue", + "methods", + "pkgbuild", + "rlang", + "rprojroot", + "utils", + "withr" + ], + "Hash": "876c618df5ae610be84356d5d7a5d124" + }, + "processx": { + "Package": "processx", + "Version": "3.8.4", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "R6", + "ps", + "utils" + ], + "Hash": "0c90a7d71988856bad2a2a45dd871bb9" + }, + "promises": { + "Package": "promises", + "Version": "1.3.0", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R6", + "Rcpp", + "fastmap", + "later", + "magrittr", + "rlang", + "stats" + ], + "Hash": "434cd5388a3979e74be5c219bcd6e77d" + }, + "ps": { + "Package": "ps", + "Version": "1.7.6", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "utils" + ], + "Hash": "dd2b9319ee0656c8acf45c7f40c59de7" + }, + "rappdirs": { + "Package": "rappdirs", + "Version": "0.3.3", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R" + ], + "Hash": "5e3c5dc0b071b21fa128676560dbe94d" + }, + "remotes": { + "Package": "remotes", + "Version": "2.5.0", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "methods", + "stats", + "tools", + "utils" + ], + "Hash": "3ee025083e66f18db6cf27b56e23e141" + }, + "rlang": { + "Package": "rlang", + "Version": "1.1.4", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "utils" + ], + "Hash": "3eec01f8b1dee337674b2e34ab1f9bc1" + }, + "rprojroot": { + "Package": "rprojroot", + "Version": "2.0.4", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R" + ], + "Hash": "4c8415e0ec1e29f3f4f6fc108bef0144" + }, + "sass": { + "Package": "sass", + "Version": "0.4.9.9000", + "Source": "GitHub", + "RemoteType": "github", + "RemoteHost": "api.github.com", + "RemoteRepo": "sass", + "RemoteUsername": "rstudio", + "RemotePkgRef": "rstudio/sass", + "RemoteRef": "HEAD", + "RemoteSha": "9228fcf39deecfe32b7cb90ed40690338a18acba", + "Requirements": [ + "R6", + "fs", + "htmltools", + "rappdirs", + "rlang" + ], + "Hash": "3eea8b7c0d780b0d04fff9eb99dc7e6d" + }, + "shiny": { + "Package": "shiny", + "Version": "1.8.1.1", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "R6", + "bslib", + "cachem", + "commonmark", + "crayon", + "fastmap", + "fontawesome", + "glue", + "grDevices", + "htmltools", + "httpuv", + "jsonlite", + "later", + "lifecycle", + "methods", + "mime", + "promises", + "rlang", + "sourcetools", + "tools", + "utils", + "withr", + "xtable" + ], + "Hash": "54b26646816af9960a4c64d8ceec75d6" + }, + "sourcetools": { + "Package": "sourcetools", + "Version": "0.1.7-1", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R" + ], + "Hash": "5f5a7629f956619d519205ec475fe647" + }, + "withr": { + "Package": "withr", + "Version": "3.0.0", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "grDevices", + "graphics" + ], + "Hash": "d31b6c62c10dcf11ec530ca6b0dd5d35" + }, + "xtable": { + "Package": "xtable", + "Version": "1.8-4", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "stats", + "utils" + ], + "Hash": "b8acdf8af494d9ec19ccb2481a9b11c2" + }, + "yaml": { + "Package": "yaml", + "Version": "2.3.8", + "Source": "Repository", + "Repository": "CRAN", + "Hash": "29240487a071f535f5e5d5a323b7afbd" + } + } +} diff --git a/dev/deployment.R b/dev/deployment.R new file mode 100644 index 0000000..eaf0502 --- /dev/null +++ b/dev/deployment.R @@ -0,0 +1,46 @@ +require(googleAuthR) +require(googleCloudRunner) +require(devtools) +require(golem) +require(dockerfiler) +require(config) + +# Check & Build ----------------------------------------------------------- +devtools::check() +devtools::build() + +# Dockerfile -------------------------------------------------------------- +golem::add_dockerfile() + +# Deployment ------------------------------------------------------------- +library(googleCloudRunner) +options(cli.ignore_unknown_rstudio_theme = TRUE) + +gcp_config <- config::get("gcp", file = "inst/config.yml") + +Sys.setenv( + "GCE_DEFAULT_PROJECT_ID" = gcp_config$project_id, + "GAR_CLIENT_JSON" = gcp_config$client_json, + "GCE_AUTH_FILE" = gcp_config$auth_file, + "GCS_DEFAULT_BUCKET" = gcp_config$bucket, + "CR_REGION" = gcp_config$region, + "CR_BUILD_EMAIL" = gcp_config$build_email +) + +googleCloudRunner::cr_deploy_docker( + local = getwd(), + image_name = pkgload::pkg_name(), + remote = pkgload::pkg_name(), + tag = c("latest", "$BUILD_ID"), + timeout = 600L, + bucket = gcp_config$bucket, + projectId = gcp_config$project_id, + launch_browser = TRUE, + kaniko_cache = TRUE, + predefinedAcl = "bucketOwnerFullControl" +) + +# golem::add_dockerfile_with_renv( +# output_dir = fs::path(getwd(), "build"), +# from = "rocker/r-ver:latest" +# ) diff --git a/dev/run_local.R b/dev/run_local.R new file mode 100644 index 0000000..b0472c6 --- /dev/null +++ b/dev/run_local.R @@ -0,0 +1,16 @@ +# Set options here +options(shiny.app.prod = FALSE) # TRUE = production mode, FALSE = development mode + +# Comment this if you don't want the app to be served on a random port +options(shiny.port = httpuv::randomPort()) + +# Detach all loaded packages and clean your environment +detach_all_attached() +# rm(list=ls(all.names = TRUE)) + +# Document and reload your package +devtools::document() +pkgload::load_all() + +# Run the application +run_app()