diff --git a/.Rbuildignore b/.Rbuildignore
index c460e46a..40b216b1 100644
--- a/.Rbuildignore
+++ b/.Rbuildignore
@@ -22,3 +22,5 @@
^Meta$
^\.github$
^revdep$
+README.html
+^CRAN-SUBMISSION$
diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md
new file mode 100644
index 00000000..2f36bb85
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/bug_report.md
@@ -0,0 +1,30 @@
+---
+name: Bug report
+about: Create a report to help us improve
+title: "[BUG]"
+labels: bug
+assignees: ColinFay
+
+---
+
+**Describe the bug**
+A clear and concise description of what the bug is.
+
+**To Reproduce**
+Steps to reproduce the behavior:
+1.
+1. ...
+2. ...
+
+**Expected behavior**
+A clear and concise description of what you expected to happen.
+
+**Screenshots**
+If applicable, add screenshots to help explain your problem.
+
+**session info**
+
+please insert here the output of `devtools::session_info()`
+
+**Additional context**
+Add any other context about the problem here.
diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md
new file mode 100644
index 00000000..524940e5
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/feature_request.md
@@ -0,0 +1,20 @@
+---
+name: Feature request
+about: Suggest an idea for this project
+title: "[FR]"
+labels: enhancement
+assignees: ''
+
+---
+
+**Is your feature request related to a problem? Please describe.**
+A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
+
+**Describe the solution you'd like**
+A clear and concise description of what you want to happen.
+
+**Describe alternatives you've considered**
+A clear and concise description of any alternative solutions or features you've considered.
+
+**Additional context**
+Add any other context or screenshots about the feature request here.
diff --git a/.github/ISSUE_TEMPLATE/todo.md b/.github/ISSUE_TEMPLATE/todo.md
new file mode 100644
index 00000000..d6bcae43
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/todo.md
@@ -0,0 +1,34 @@
+---
+name: todo
+about: Internal issue template for golem developers
+title: ''
+labels: ''
+assignees: ''
+
+---
+
+## User - Validation
+
++ [ ] First thing to do to validate this as an external user
++ [ ] Second thing to do to validate this as an external user
+
+## Dev - Tech
+
+_A paragraph that details what this functionality does and how it will be implemented._
+
++ [ ] A sentence that sums up a feature
+ + [ ] Implementation number 1
+ + [ ] Implementation number 2
+ + [ ] Technical validation
++ [ ] A sentence that sums up a feature
+ + [ ] Implementation number 1
+ + [ ] Implementation number 2
+ + [ ] Technical validation
+
+## Estimated time
+
+01h00.
+
++ [ ] Add the estimate as a comment with `/estimate`
++ [ ] When I close this issue, `devtools::check()` is 0 0 0
++ [ ] When I close the issue, I've written the time spent solving this issue, using `/spent`
diff --git a/.github/workflows/R-CMD-check.yaml b/.github/workflows/R-CMD-check.yaml
new file mode 100644
index 00000000..a3ac6182
--- /dev/null
+++ b/.github/workflows/R-CMD-check.yaml
@@ -0,0 +1,49 @@
+# Workflow derived from https://github.com/r-lib/actions/tree/v2/examples
+# Need help debugging build failures? Start at https://github.com/r-lib/actions#where-to-find-help
+on:
+ push:
+ branches: [main, master]
+ pull_request:
+ branches: [main, master]
+
+name: R-CMD-check
+
+jobs:
+ R-CMD-check:
+ runs-on: ${{ matrix.config.os }}
+
+ name: ${{ matrix.config.os }} (${{ matrix.config.r }})
+
+ strategy:
+ fail-fast: false
+ matrix:
+ config:
+ - {os: macos-latest, r: 'release'}
+ - {os: windows-latest, r: 'release'}
+ - {os: ubuntu-latest, r: 'devel', http-user-agent: 'release'}
+ - {os: ubuntu-latest, r: 'release'}
+ - {os: ubuntu-latest, r: 'oldrel-1'}
+
+ env:
+ GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }}
+ R_KEEP_PKG_SOURCE: yes
+
+ steps:
+ - uses: actions/checkout@v3
+
+ - uses: r-lib/actions/setup-pandoc@v2
+
+ - uses: r-lib/actions/setup-r@v2
+ with:
+ r-version: ${{ matrix.config.r }}
+ http-user-agent: ${{ matrix.config.http-user-agent }}
+ use-public-rspm: true
+
+ - uses: r-lib/actions/setup-r-dependencies@v2
+ with:
+ extra-packages: any::rcmdcheck
+ needs: check
+
+ - uses: r-lib/actions/check-r-package@v2
+ with:
+ upload-snapshots: true
diff --git a/.github/workflows/check-standard.yaml b/.github/workflows/check-standard.yaml
deleted file mode 100644
index 0b0fa965..00000000
--- a/.github/workflows/check-standard.yaml
+++ /dev/null
@@ -1,112 +0,0 @@
-# For help debugging build failures open an issue on the RStudio community with the 'github-actions' tag.
-# https://community.rstudio.com/new-topic?category=Package%20development&tags=github-actions
-on:
- push:
- branches:
- - main
- - master
- - dev
- pull_request:
- branches:
- - main
- - master
- - dev
-
-name: R-CMD-check
-
-jobs:
- R-CMD-check:
- runs-on: ${{ matrix.config.os }}
-
- name: ${{ matrix.config.os }} (${{ matrix.config.r }})
-
- strategy:
- fail-fast: false
- matrix:
- config:
- - { os: windows-latest, r: "release" }
- - { os: macOS-latest, r: "release" }
- - {
- os: ubuntu-20.04,
- r: "release",
- rspm: "https://packagemanager.rstudio.com/cran/__linux__/focal/latest",
- }
-
- env:
- R_REMOTES_NO_ERRORS_FROM_WARNINGS: true
- RSPM: ${{ matrix.config.rspm }}
- GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }}
-
- steps:
- - uses: actions/checkout@v2
-
- - uses: r-lib/actions/setup-r@v1
- with:
- r-version: ${{ matrix.config.r }}
-
- - uses: r-lib/actions/setup-pandoc@v1
-
- - name: Query dependencies
- run: |
- install.packages('remotes')
- saveRDS(remotes::dev_package_deps(dependencies = TRUE), ".github/depends.Rds", version = 2)
- writeLines(sprintf("R-%i.%i", getRversion()$major, getRversion()$minor), ".github/R-version")
- shell: Rscript {0}
-
- - name: Cache R packages
- if: runner.os != 'Windows'
- uses: actions/cache@v2
- with:
- path: ${{ env.R_LIBS_USER }}
- key: ${{ runner.os }}-${{ hashFiles('.github/R-version') }}-1-${{ hashFiles('.github/depends.Rds') }}
- restore-keys: ${{ runner.os }}-${{ hashFiles('.github/R-version') }}-1-
-
- - name: Install system dependencies
- if: runner.os == 'Linux'
- run: |
- while read -r cmd
- do
- eval sudo $cmd
- done < <(Rscript -e 'writeLines(remotes::system_requirements("ubuntu", "20.04"))')
-
- - name: Install dependencies
- run: |
- remotes::install_deps(dependencies = TRUE)
- remotes::install_cran("rcmdcheck")
- shell: Rscript {0}
-
- - name: Check
- env:
- _R_CHECK_CRAN_INCOMING_REMOTE_: false
- run: |
- options(crayon.enabled = TRUE)
- rcmdcheck::rcmdcheck(args = c("--no-manual", "--as-cran"), error_on = "warning", check_dir = "check")
- shell: Rscript {0}
-
- - name: Manual Test
- if: runner.os != 'Windows'
- env:
- GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }}
- run: |
- source("inst/mantests/build.R")
- shell: Rscript {0}
-
- # - name: Pushes to another repository
- # uses: cpina/github-action-push-to-another-repository@main
- # if: runner.os == 'Linux'
- # env:
- # API_TOKEN_GITHUB: ${{ secrets.API_TOKEN_GITHUB }}
- # with:
- # source-directory: "inst/golemmetrics"
- # destination-github-username: "colinfay"
- # destination-repository-username: "thinkr-open"
- # destination-repository-name: "golemmetrics"
- # user-email: contact@colinfay.me
- # target-branch: main
-
- - name: Upload check results
- if: failure()
- uses: actions/upload-artifact@main
- with:
- name: ${{ runner.os }}-r${{ matrix.config.r }}-results
- path: check
diff --git a/.github/workflows/test-coverage.yaml b/.github/workflows/test-coverage.yaml
new file mode 100644
index 00000000..2c5bb502
--- /dev/null
+++ b/.github/workflows/test-coverage.yaml
@@ -0,0 +1,50 @@
+# Workflow derived from https://github.com/r-lib/actions/tree/v2/examples
+# Need help debugging build failures? Start at https://github.com/r-lib/actions#where-to-find-help
+on:
+ push:
+ branches: [main, master]
+ pull_request:
+ branches: [main, master]
+
+name: test-coverage
+
+jobs:
+ test-coverage:
+ runs-on: ubuntu-latest
+ env:
+ GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }}
+
+ steps:
+ - uses: actions/checkout@v3
+
+ - uses: r-lib/actions/setup-r@v2
+ with:
+ use-public-rspm: true
+
+ - uses: r-lib/actions/setup-r-dependencies@v2
+ with:
+ extra-packages: any::covr
+ needs: coverage
+
+ - name: Test coverage
+ run: |
+ covr::codecov(
+ quiet = FALSE,
+ clean = FALSE,
+ install_path = file.path(Sys.getenv("RUNNER_TEMP"), "package")
+ )
+ shell: Rscript {0}
+
+ - name: Show testthat output
+ if: always()
+ run: |
+ ## --------------------------------------------------------------------
+ find ${{ runner.temp }}/package -name 'testthat.Rout*' -exec cat '{}' \; || true
+ shell: bash
+
+ - name: Upload test results
+ if: failure()
+ uses: actions/upload-artifact@v3
+ with:
+ name: coverage-test-failures
+ path: ${{ runner.temp }}/package
diff --git a/CRAN-SUBMISSION b/CRAN-SUBMISSION
new file mode 100644
index 00000000..8608538e
--- /dev/null
+++ b/CRAN-SUBMISSION
@@ -0,0 +1,3 @@
+Version: 0.4.0
+Date: 2023-03-10 13:02:19 UTC
+SHA: ce67fa5e76d40f1ca68b6dda10064bae37fbcb6e
diff --git a/DESCRIPTION b/DESCRIPTION
index 5117b403..61338070 100644
--- a/DESCRIPTION
+++ b/DESCRIPTION
@@ -1,72 +1,44 @@
Package: golem
Title: A Framework for Robust Shiny Applications
-Version: 0.3.2.9004
-Authors@R:
- c(person(given = "Colin",
- family = "Fay",
- role = c("cre", "aut"),
- email = "contact@colinfay.me",
- comment = c(ORCID = "0000-0001-7343-1846")),
- person(given = "Vincent",
- family = "Guyader",
- role = "aut",
- email = "vincent@thinkr.fr",
- comment = c(ORCID = "0000-0003-0671-9270", "previous maintainer")),
- person(given = "Sébastien",
- family = "Rochette",
- role = "aut",
- email = "sebastien@thinkr.fr",
- comment = c(ORCID = "0000-0002-1565-9313")),
- person(given = "Cervan",
- family = "Girard",
- role = "aut",
- email = "cervan@thinkr.fr",
- comment = c(ORCID = "0000-0002-4816-4624")),
- person(given = "Novica",
- family = "Nakov",
- role = "ctb",
- email = "nnovica@gmail.com"),
- person(given = "David",
- family = "Granjon",
- role = "ctb",
- email = "dgranjon@ymail.com"),
- person(given = "Arthur",
- family = "Bréant",
- role = "ctb",
- email = "arthur@thinkr.fr"),
- person(given = "Antoine",
- family = "Languillaume",
- role = "ctb",
- email = "antoine@thinkr.fr"),
- person(given = "ThinkR",
- role = "cph"))
+Version: 0.4.10
+Authors@R: c(
+ person("Colin", "Fay", , "contact@colinfay.me", role = c("cre", "aut"),
+ comment = c(ORCID = "0000-0001-7343-1846")),
+ person("Vincent", "Guyader", , "vincent@thinkr.fr", role = "aut",
+ comment = c(ORCID = "0000-0003-0671-9270", "previous maintainer")),
+ person("Sébastien", "Rochette", , "sebastien@thinkr.fr", role = "aut",
+ comment = c(ORCID = "0000-0002-1565-9313")),
+ person("Cervan", "Girard", , "cervan@thinkr.fr", role = "aut",
+ comment = c(ORCID = "0000-0002-4816-4624")),
+ person("Novica", "Nakov", , "nnovica@gmail.com", role = "ctb"),
+ person("David", "Granjon", , "dgranjon@ymail.com", role = "ctb"),
+ person("Arthur", "Bréant", , "arthur@thinkr.fr", role = "ctb"),
+ person("Antoine", "Languillaume", , "antoine@thinkr.fr", role = "ctb"),
+ person("ThinkR", role = "cph")
+ )
Description: An opinionated framework for building a production-ready
'Shiny' application. This package contains a series of tools for
building a robust 'Shiny' application from start to finish.
License: MIT + file LICENSE
URL: https://github.com/ThinkR-open/golem
BugReports: https://github.com/ThinkR-open/golem/issues
-Depends:
+Depends:
R (>= 3.0)
-Imports:
+Imports:
attempt (>= 0.3.0),
- cli (>= 2.0.0),
config,
- crayon,
- desc,
- fs,
here,
htmltools,
- rlang,
- rstudioapi,
+ rlang (>= 1.0.0),
shiny (>= 1.5.0),
- usethis (>= 1.6.0),
utils,
yaml
Suggests:
covr,
+ cli (>= 2.0.0),
+ crayon,
devtools,
- dockerfiler (>= 0.1.4),
+ dockerfiler (>= 0.2.0),
knitr,
pkgload,
pkgbuild,
@@ -82,11 +54,16 @@ Suggests:
testthat,
tools,
withr,
- attachment
-VignetteBuilder:
+ attachment (>= 0.2.5),
+ renv,
+ usethis (>= 1.6.0),
+ fs,
+ rstudioapi,
+ desc
+VignetteBuilder:
knitr
Config/testthat/edition: 3
Encoding: UTF-8
Language: en-US
Roxygen: list(markdown = TRUE)
-RoxygenNote: 7.1.2
+RoxygenNote: 7.2.3
diff --git a/NAMESPACE b/NAMESPACE
index 468dedd2..5c44bf87 100644
--- a/NAMESPACE
+++ b/NAMESPACE
@@ -5,6 +5,9 @@ export(add_css_file)
export(add_dockerfile)
export(add_dockerfile_heroku)
export(add_dockerfile_shinyproxy)
+export(add_dockerfile_with_renv)
+export(add_dockerfile_with_renv_heroku)
+export(add_dockerfile_with_renv_shinyproxy)
export(add_fct)
export(add_html_template)
export(add_js_file)
@@ -12,6 +15,7 @@ export(add_js_handler)
export(add_js_input_binding)
export(add_js_output_binding)
export(add_module)
+export(add_partial_html_template)
export(add_resource_path)
export(add_rstudioconnect_file)
export(add_sass_file)
@@ -37,15 +41,19 @@ export(expect_shinytag)
export(expect_shinytaglist)
export(favicon)
export(fill_desc)
+export(get_current_config)
export(get_golem_name)
export(get_golem_options)
export(get_golem_version)
export(get_golem_wd)
export(get_sysreqs)
+export(install_dev_deps)
export(invoke_js)
+export(is_golem)
export(is_running)
export(js_handler_template)
export(js_template)
+export(maintenance_page)
export(make_dev)
export(message_dev)
export(module_template)
@@ -72,6 +80,7 @@ export(use_internal_file)
export(use_internal_html_template)
export(use_internal_js_file)
export(use_module_test)
+export(use_readme_rmd)
export(use_recommended_deps)
export(use_recommended_tests)
export(use_utils_server)
@@ -85,43 +94,13 @@ importFrom(attempt,is_try_error)
importFrom(attempt,stop_if)
importFrom(attempt,stop_if_not)
importFrom(attempt,without_warning)
-importFrom(cli,cat_bullet)
-importFrom(cli,cat_line)
-importFrom(cli,cat_rule)
-importFrom(cli,cli_alert_info)
importFrom(config,get)
-importFrom(desc,desc_get_deps)
-importFrom(desc,description)
-importFrom(fs,dir_copy)
-importFrom(fs,dir_create)
-importFrom(fs,dir_exists)
-importFrom(fs,file_copy)
-importFrom(fs,file_create)
-importFrom(fs,file_delete)
-importFrom(fs,file_exists)
-importFrom(fs,path)
-importFrom(fs,path_abs)
-importFrom(fs,path_file)
importFrom(htmltools,htmlDependency)
-importFrom(rstudioapi,documentSaveAll)
-importFrom(rstudioapi,getSourceEditorContext)
-importFrom(rstudioapi,hasFun)
-importFrom(rstudioapi,isAvailable)
-importFrom(rstudioapi,modifyRange)
-importFrom(rstudioapi,navigateToFile)
-importFrom(rstudioapi,openProject)
-importFrom(rstudioapi,sourceMarkers)
importFrom(shiny,addResourcePath)
importFrom(shiny,getShinyOption)
+importFrom(shiny,htmlTemplate)
importFrom(shiny,includeScript)
importFrom(shiny,tags)
-importFrom(usethis,create_project)
-importFrom(usethis,proj_set)
-importFrom(usethis,use_build_ignore)
-importFrom(usethis,use_latest_dependencies)
-importFrom(usethis,use_package)
-importFrom(usethis,use_spell_check)
-importFrom(usethis,use_testthat)
importFrom(utils,capture.output)
importFrom(utils,file.edit)
importFrom(utils,getFromNamespace)
diff --git a/NEWS.md b/NEWS.md
index 4fc05971..b75e8e37 100644
--- a/NEWS.md
+++ b/NEWS.md
@@ -1,107 +1,162 @@
-> Notes: the # between parenthesis referes to the related issue on GitHub, and the @ refers to an external contributor solving this issue.
+> Notes: the # between parenthesis referes to the related issue on GitHub, and the @ refers to an external contributor solving this issue.
-# golem 0.3.2.9000+
+# 0.4.1 to 0.5.0
-### Soft deprecated
+## New functions
+* `is_golem()` tries to guess if the current folder is a `{golem}`-based app (#836)
-### Hard deprecated
+* `use_readme_rmd()` adds a {golem} specific READM.Rmd (@ilyaZar, #1011)
+## New features / user visible changes
-## New functions
++ `add_fct()` now adds the skeleton for a function (#1004, @ilyaZar)
++ The module skeleton now stick to tidyverse style (#1019, @ni2scmn)
-## New features
++ Better comments to `fill_desc()` in `01_start.R` (#1021, @ilyaZar)
+
++ `01_start.R` now has a call to `usethis::use_git_remote()` (#1015, @ilyaZar)
+
++ Test for utilsui and server now has full code coverate (#1020, @ilyaZar)
+
++ When setting a new name, golem now browses tests & vignettes (#805, @ilyaZar)
+
+## Bug fix
+
++ Docker commands now take the `-it` flag so it can be killed with `^C` (#, @ivokwee)
-+ The following hard dependencies have been moved to soft dependencies, as you'll only need them while developing: `{pkgload}`, `{roxygen2}`
++ add_module() now behaves correctly when trying to use `mod_mod_XXX` (#997, @ilyaZar)
-+ Soft dependency check is now done via `rlang::check_installed()` (#835)
+## Internal changes
-+ `golem::run_dev()` has been refactored to match the behavior of other functions, notably it now uses `golem::get_golem_wd()` to find the current working dir.
+# 0.4.0
+
+## New functions
+
+- Add `add_partial_html_template()` to create a partial html template, with only a div and a `{{ }}` (@nathansquan #858).
+
+## New features / user visible changes
+
+- Dev hard dependencies have been moved to soft dependencies. You can see the list with `golem:::dev_deps`. They can be installed via `golem::install_dev_deps()`.
+- Soft dependency check is now done via `rlang::check_installed()` (#835)
+- `golem::run_dev()` has been refactored to match the behavior of other functions, notably it now uses `golem::get_golem_wd()` to find the current working dir.
+- `{golem}` now depends on `{rlang}` version >= 1.0.0
+- Functions that print to the console are now quiet if `options("golem.quiet" = TRUE)`, #793
+- Small documentation update in dockerfile related functions (#939)
+- `fill_desc()` now allows to set the version (#877)
+- Setting the Environment variable `GOLEM_MAINTENANCE_ACTIVE` to `TRUE` active the maintenance mode of your app
+- `golem::run_dev()` now save all open documents before sourcing the `dev/run_dev.R` file
+- When creating an app, you'll get a message if the dev deps are not all installed (#915)
+- 03_deploy now contains an example of sending the app to PositConnect or Shinyapps.io (#923)
## Bug fix
-+ The message after htmlTemplate creation now suggests to add in the UI, not only in app_ui.R (#861)
+- The message after htmlTemplate creation now suggests to add in the UI, not only in app_ui.R (#861)
+- The Deprecation message for `use_recommended_deps` no longer suggest to user `use_recommended_deps` (#900)
+- The setting of the config file has been unified so that we are sure to keep the !expr in `golem_set_wd()`, and the codebase has been simplified for this (#709).
+- The functions adding files can no longer take a `name` argument that has length() > 1. This used to cause some bugs (#781)
+- The typo in `install.packages()` in 02_dev.R has been corrected (@asiripanich)
+- `add_dockerfile_with_renv()` now works well with uppercase in package name
+- improve `get_golem_options()` documentation
## Internal changes
++ `add_dockerfile_with_renv` now works well with uppercase in package name
+
+# golem 0.3.5
+Update in the tests for CRAN (commented a test that made new version of testthat fail).
+
+# golem 0.3.4
+
+Update in the tests for CRAN (skip not installed + examples).
+
+# golem 0.3.3
+
+## New functions
+
+- `add_dockerfile_with_renv()`, `add_dockerfile_with_renv_heroku()` and `add_dockerfile_with_renv_shinyproxy()` build Dockerfiles that rely on `{renv}`
+
+### Soft deprecated
+
+- `add_dockerfile`, `add_dockerfile_shinyproxy()` and `add_dockerfile_heroku()` now recommend to switch to their `_with_renv_` counterpart
# golem 0.3.2 (CRAN VERSION)
### Soft deprecated
-+ `use_recommended_deps()` is now soft deprecated (#786)
+- `use_recommended_deps()` is now soft deprecated (#786)
### Hard deprecated
-+ The `html` parameter in `expect_html_equal()` is no longer in use (#55).
+- The `html` parameter in `expect_html_equal()` is no longer in use (#55).
## New functions
-+ `add_sass_file()` creates a .sass file in inst/app/www (#768)
+- `add_sass_file()` creates a .sass file in inst/app/www (#768)
-+ `use_module_test()` creates a test skeleton for a module (#725)
+- `use_module_test()` creates a test skeleton for a module (#725)
## New features
-+ The `02_dev.R` file now suggests using `attachment::att_amend_desc()` (#787)
+- The `02_dev.R` file now suggests using `attachment::att_amend_desc()` (#787)
-+ `use_code_of_conduct()` in dev script now has the contact param (#812)
+- `use_code_of_conduct()` in dev script now has the contact param (#812)
-+ All `with_test` params are now TRUE in the dev script (#801)
-
-+ `test-golem-recommended` now has two new tests for `app_sys` and `get_golem_config` (#751)
+- All `with_test` params are now TRUE in the dev script (#801)
-+ `use_utils_ui()` `use_utils_server()` & now come with a `with_test` parameter that adds a test file for theses functions (#625 & #801)
+- `test-golem-recommended` now has two new tests for `app_sys` and `get_golem_config` (#751)
-+ `{golem}` now checks if a module exists before adding a module related file (#779)
+- `use_utils_ui()` `use_utils_server()` & now come with a `with_test` parameter that adds a test file for theses functions (#625 & #801)
-+ Every `{rstudioapi}` calls is now conditionned by the availabily of this function (#776)
+- `{golem}` now checks if a module exists before adding a module related file (#779)
-+ `use_external_*` functions no longer suggest to "Go to" (#713, @novica)
-
-+ `create_golem()` now comes with `with_git` parameter that can be used to initialize git repository while creating a project template
+- Every `{rstudioapi}` calls is now conditionned by the availabily of this function (#776)
-+ `use_recommended_tests()` now comes with `testServer` (#720).
+- `use_external_*` functions no longer suggest to "Go to" (#713, @novica)
-+ `expect_html_equal()` now uses `testthat::expect_snapshot()` (#55).
+- `create_golem()` now comes with `with_git` parameter that can be used to initialize git repository while creating a project template
-+ `add_modules()`, `add_fct()` and `add_utils()` now come with a `with_test` parameter that can be turned on to add a test file to the module (#719 & #141)
+- `use_recommended_tests()` now comes with `testServer` (#720).
-+ /!\ All docker related functions have been moved to `{dockerfiler}`. This is more or less a breaking change, cause you'll need to install `{dockerfiler}` > 0.1.4 in order to build the Dockerfile __but__ `{golem}` will ask you to install `{dockerfiler}` > 0.1.4 if it can't find it, (#412)
+- `expect_html_equal()` now uses `testthat::expect_snapshot()` (#55).
-+ Modules ID no longer contain an `_ui_` element, (#651, @MargotBr)
+- `add_modules()`, `add_fct()` and `add_utils()` now come with a `with_test` parameter that can be turned on to add a test file to the module (#719 & #141)
-+ run_dev now has `options(shiny.port = httpuv::randomPort())` to prevent the browser from caching the CSS & JS files (#675)
+- /!\ All docker related functions have been moved to `{dockerfiler}`. This is more or less a breaking change, cause you'll need to install `{dockerfiler}` > 0.1.4 in order to build the Dockerfile **but** `{golem}` will ask you to install `{dockerfiler}` > 0.1.4 if it can't find it, (#412)
-+ You can now specify the path to R in `expect_running()`.
+- Modules ID no longer contain an `_ui_` element, (#651, @MargotBr)
+
+- run_dev now has `options(shiny.port = httpuv::randomPort())` to prevent the browser from caching the CSS & JS files (#675)
+
+- You can now specify the path to R in `expect_running()`.
## Bug fix
-+ Fixed a bug in the printing of the htmlTemplate code (#827)
+- Fixed a bug in the printing of the htmlTemplate code (#827)
-+ We now require the correct `{usethis}` version (822)
+- We now require the correct `{usethis}` version (822)
-+ `golem::amend_config()` now keeps the `!expr` (#709, @teofiln)
+- `golem::amend_config()` now keeps the `!expr` (#709, @teofiln)
-+ recommended tests now use `expect_type()` instead of `expect_is`, which was deprecated from `{testthat}` (#671)
+- recommended tests now use `expect_type()` instead of `expect_is`, which was deprecated from `{testthat}` (#671)
-+ Fixed check warning when using `golem::use_utils_server()` (#678),
+- Fixed check warning when using `golem::use_utils_server()` (#678),
-+ Fixed issue with expect_running & path to R (#700, @waiteb5)
+- Fixed issue with expect_running & path to R (#700, @waiteb5)
-+ `expect_running()` now find R.exe on windows.
+- `expect_running()` now find R.exe on windows.
-+ `use_recommended_tests()` no longer add `{processx}` to the `DESCRIPTION` (#710)
+- `use_recommended_tests()` no longer add `{processx}` to the `DESCRIPTION` (#710)
-+ `bundle_resource()` does not include empty stylesheet anymore (#689, @erikvona)
+- `bundle_resource()` does not include empty stylesheet anymore (#689, @erikvona)
## Internal changes
-+ Create `{golem}` is more robust and now comes with an `overwrite` argument (#777)
+- Create `{golem}` is more robust and now comes with an `overwrite` argument (#777)
-+ `{testthat}` and `{rlang}` are no longer hard dependencies (#742)
+- `{testthat}` and `{rlang}` are no longer hard dependencies (#742)
# golem 0.3.1 (CRAN Version)
@@ -109,316 +164,315 @@
### `add_*`
-+ You can now create a skeleton for a Shiny input binding using the `golem::add_js_binding("name")` function (#452, @DivadNojnarg)
+- You can now create a skeleton for a Shiny input binding using the `golem::add_js_binding("name")` function (#452, @DivadNojnarg)
-+ You can now create a skeleton for a Shiny output binding using the `golem::add_js_output_binding("name")` function (@DivadNojnarg)
+- You can now create a skeleton for a Shiny output binding using the `golem::add_js_output_binding("name")` function (@DivadNojnarg)
-+ `add_html_template()` creates an htmlTemplate.
+- `add_html_template()` creates an htmlTemplate.
### `use_*`
-+ `use_external_file()` allows to add any file to the `www` folder, `use_external_css_file()`, `use_external_html_template()`, and `use_external_js_file()` will download them from a URL (#295, #491).
+- `use_external_file()` allows to add any file to the `www` folder, `use_external_css_file()`, `use_external_html_template()`, and `use_external_js_file()` will download them from a URL (#295, #491).
-+ `use_internal_css_file()`, `use_internal_file()`, `use_internal_html_template()`, `use_internal_js_file()` functions allow to any file from the current computer to the `www` folder (@KasperThystrup, #529)
+- `use_internal_css_file()`, `use_internal_file()`, `use_internal_html_template()`, `use_internal_js_file()` functions allow to any file from the current computer to the `www` folder (@KasperThystrup, #529)
### Tests helper
-+ `expect_running()` expects the current shiny app to be running.
+- `expect_running()` expects the current shiny app to be running.
### Hooks
-+ Every `{golem}` project now have a `project_hook` that is launched after the project creation.
+- Every `{golem}` project now have a `project_hook` that is launched after the project creation.
-+ `module_template()` is the default function for `{golem}` module creation. Users will now be able to define a custom `module_template()` function for `add_module()`, allowing to extend `{golem}` with your own module creation function. See ?golem::module_template for more info (#365)
+- `module_template()` is the default function for `{golem}` module creation. Users will now be able to define a custom `module_template()` function for `add_module()`, allowing to extend `{golem}` with your own module creation function. See ?golem::module_template for more info (#365)
-+ `add_js_` and `add_css_` functions now have a template function, allowing to pass a file constructor.
+- `add_js_` and `add_css_` functions now have a template function, allowing to pass a file constructor.
### Misc
-+ `is_running()` checks if the current running application is a `{golem}` based application (#366)
+- `is_running()` checks if the current running application is a `{golem}` based application (#366)
-+ `utils_ui.R` now contains a "make_action_button()" function (#457, @DivadNojnarg)
+- `utils_ui.R` now contains a "make_action_button()" function (#457, @DivadNojnarg)
-+ `run_dev()` launches the `run_dev.R` script (#478, @KoderKow)
+- `run_dev()` launches the `run_dev.R` script (#478, @KoderKow)
-+ `run_dev()` performs a check on golem name.
+- `run_dev()` performs a check on golem name.
-+ `sanity_check()` function has been added to check for any 'browser()' or commented #TODO / #TOFIX / #BUG in the code (#1354 @Swechhya)
+- `sanity_check()` function has been added to check for any 'browser()' or commented #TODO / #TOFIX / #BUG in the code (#1354 @Swechhya)
## New features
-+ The modules are now created with the new skeleton when the installed version of `{shiny}` is >= 1.5.0.
+- The modules are now created with the new skeleton when the installed version of `{shiny}` is >= 1.5.0.
-+ `use_external_*()` function don't open files by default (#404)
+- `use_external_*()` function don't open files by default (#404)
-+ `use_recommended_tests*()` now calls ` use_spell_check()` (#430)
+- `use_recommended_tests*()` now calls ` use_spell_check()` (#430)
-+ The `02_dev.R` now includes more CI links
+- The `02_dev.R` now includes more CI links
-+ `golem::expect_running()` is now bundled in default tests
+- `golem::expect_running()` is now bundled in default tests
-+ Default tests now test for functions formals (#437)
+- Default tests now test for functions formals (#437)
-+ You can now pass arguments to internal `roxygenise()` & `load_all()` (#467)
+- You can now pass arguments to internal `roxygenise()` & `load_all()` (#467)
-+ `Bundle_resources()` now handle subfolders (#446)
+- `Bundle_resources()` now handle subfolders (#446)
-+ `run_app()` now includes the default arguments of `shinyApp()` (#254, @chasemc)
+- `run_app()` now includes the default arguments of `shinyApp()` (#254, @chasemc)
-+ `create_golem()` now adds strict dependency versions (#466)
+- `create_golem()` now adds strict dependency versions (#466)
-+ `{golem}` app now comes with a meta tags "app-builder", which default to "golem", and that can be changed or turn off in `bundle_resources()`.
+- `{golem}` app now comes with a meta tags "app-builder", which default to "golem", and that can be changed or turn off in `bundle_resources()`.
-+ `with_golem_options` can now explicit calls `print` on the `app` object, solving some issues with benchmarking the application. This explicit print can be turned off by setting `print` to FALSE in `with_golem_options` (#148)
+- `with_golem_options` can now explicit calls `print` on the `app` object, solving some issues with benchmarking the application. This explicit print can be turned off by setting `print` to FALSE in `with_golem_options` (#148)
-+ `dockerignore` is now available.
+- `dockerignore` is now available.
-+ The `add_helpers` and `add_utils` now have roxygen comments (Richard Pilbery, #330)
+- The `add_helpers` and `add_utils` now have roxygen comments (Richard Pilbery, #330)
-+ `dev/03_dev.R` now has `devtools::build()` (#603)
+- `dev/03_dev.R` now has `devtools::build()` (#603)
-+ `detach_all_attached()` is now silent (#605)
+- `detach_all_attached()` is now silent (#605)
## Soft deprecated
-+ `add_ui_server_files()` is now signaled as deprecated. Please comment on https://github.com/ThinkR-open/golem/issues/445 if you want it to be kept inside the package
+- `add_ui_server_files()` is now signaled as deprecated. Please comment on https://github.com/ThinkR-open/golem/issues/445 if you want it to be kept inside the package
## Breaking changes
-+ `add_dockerfile*` function now return the `{dockerfiler}` object instead of the path to it. It allows to modify the Dockerfile object programmatically. (#493)
+- `add_dockerfile*` function now return the `{dockerfiler}` object instead of the path to it. It allows to modify the Dockerfile object programmatically. (#493)
-+ The `get_golem_config` now first look for a `GOLEM_CONFIG_ACTIVE` before looking for `R_CONFIG_ACTIVE` (#563)
+- The `get_golem_config` now first look for a `GOLEM_CONFIG_ACTIVE` before looking for `R_CONFIG_ACTIVE` (#563)
## Bug fix
-+ `add_` functions no longer append to file if it already exists (#393)
+- `add_` functions no longer append to file if it already exists (#393)
-+ `config::get()` is no longer exported to prevent namespace conflicts with `base::get()`
-
-+ fixed issue with favicon when package is built (#387)
+- `config::get()` is no longer exported to prevent namespace conflicts with `base::get()`
-+ `use_external_*()` function don't add ext if already there (#405)
+- fixed issue with favicon when package is built (#387)
-+ `create_golem` function does not modify any existing file (#423, @antoine-sachet)
+- `use_external_*()` function don't add ext if already there (#405)
-+ `add_resources_path()` now correctly handles empty folder (#395)
+- `create_golem` function does not modify any existing file (#423, @antoine-sachet)
-+ test for app launching is now skipped if not interactive()
+- `add_resources_path()` now correctly handles empty folder (#395)
-+ `add_utils` and `add_fct` now print to the console (#427, @novica)
+- test for app launching is now skipped if not interactive()
-+ Multiple CRAN repo are now correctly passed to the Dockerfile (#462)
+- `add_utils` and `add_fct` now print to the console (#427, @novica)
-+ app_config, DESC and golem-config.yml are now updated whenever you change the name of the package using a golem function (#469 )
+- Multiple CRAN repo are now correctly passed to the Dockerfile (#462)
-+ `test_recommended` now work in every case (hopefully)
+- app_config, DESC and golem-config.yml are now updated whenever you change the name of the package using a golem function (#469 )
-- `usethis::use_mit_license` does not have the `name` argument anymore so if fits new version of `{usethis}` (#594)
+- `test_recommended` now work in every case (hopefully)
-- Typo fix preventing `invoke_js("prompt")` and `invoke_js("confirm")` to work (#606)
+* `usethis::use_mit_license` does not have the `name` argument anymore so if fits new version of `{usethis}` (#594)
+
+* Typo fix preventing `invoke_js("prompt")` and `invoke_js("confirm")` to work (#606)
## Internal changes
-+ `document_and_reload()` now has `export_all = FALSE,helpers = FALSE,attach_testthat = FALSE`, allowing the function to behave more closely to what library() does (#399)
+- `document_and_reload()` now has `export_all = FALSE,helpers = FALSE,attach_testthat = FALSE`, allowing the function to behave more closely to what library() does (#399)
-+ Dockerfile generation now removes the copied file and tar.gz
+- Dockerfile generation now removes the copied file and tar.gz
# golem 0.2.1
## New functions
-+ `add_dockerfile()` was completely refactored. It now starts from r-ver, uses explicit package versions from you local machine, and tries to set as much System Requirements as possible by using `{sysreq}`, and parses and installs the Remotes tag from the DESCRIPTION (#189, #175)
-
-+ `add_dockerfile()` allow now to directly use the source of the package by mounting the source folder in the container and running `remotes::install_local()`
+- `add_dockerfile()` was completely refactored. It now starts from r-ver, uses explicit package versions from you local machine, and tries to set as much System Requirements as possible by using `{sysreq}`, and parses and installs the Remotes tag from the DESCRIPTION (#189, #175)
-+ `add_dockerfile()` now builds the tar.gz (#273)
+- `add_dockerfile()` allow now to directly use the source of the package by mounting the source folder in the container and running `remotes::install_local()`
-+ `add_fct` and `add_utils` add new files in your R folder that can hold utils and functions (#123).
+- `add_dockerfile()` now builds the tar.gz (#273)
-+ We switched from `shiny::addResourcePath()` to `golem::add_resource_path()`, which doesn't fail if the folder is empty (#223).
+- `add_fct` and `add_utils` add new files in your R folder that can hold utils and functions (#123).
-+ New JavaScript functions to use alert, prompt and confirm (#108, @zwycl)
+- We switched from `shiny::addResourcePath()` to `golem::add_resource_path()`, which doesn't fail if the folder is empty (#223).
-+ `use_external_js_file` and `use_external_css_file` are designed to download .js and .css file off the web to the appropriate directory (#130, @zwycl)
+- New JavaScript functions to use alert, prompt and confirm (#108, @zwycl)
+- `use_external_js_file` and `use_external_css_file` are designed to download .js and .css file off the web to the appropriate directory (#130, @zwycl)
## New features
-+ `{golem}` now comes with an internal config file. Please refer to the `config` Vignette for more information.
+- `{golem}` now comes with an internal config file. Please refer to the `config` Vignette for more information.
-+ `bundle_resources()` comes with every new app and bundles all the css and js files you put inside the `inst/app/www` folder, by matchine the file extension.
+- `bundle_resources()` comes with every new app and bundles all the css and js files you put inside the `inst/app/www` folder, by matchine the file extension.
-+ There is now an `app_sys()` function, which is a wrapper around `system.file(..., package = "myapp")` (#207, @novica)
+- There is now an `app_sys()` function, which is a wrapper around `system.file(..., package = "myapp")` (#207, @novica)
-+ `document_and_reload()` now stops when it fails, and returns an explicit failure message (#157)
+- `document_and_reload()` now stops when it fails, and returns an explicit failure message (#157)
-+ You can now create a golem without any comment (#171, @ArthurData)
+- You can now create a golem without any comment (#171, @ArthurData)
-+ The default `app_ui()` now has a `request` parameter, to natively handle bookmarking.
+- The default `app_ui()` now has a `request` parameter, to natively handle bookmarking.
-+ `document_and_reload()` now stops when it fails, and returns an explicit failure message (#157). It also uses `get_golem_wd()` as a default path, to be consistent with the rest of `{golem}` (#219, @j450h1)
+- `document_and_reload()` now stops when it fails, and returns an explicit failure message (#157). It also uses `get_golem_wd()` as a default path, to be consistent with the rest of `{golem}` (#219, @j450h1)
-+ `add_module` now allows to create and `fct_` and an `utils_` file (#154, @novica)
+- `add_module` now allows to create and `fct_` and an `utils_` file (#154, @novica)
-+ `golem::detach_all_attached()` is now silent (#186, @annakau)
+- `golem::detach_all_attached()` is now silent (#186, @annakau)
-+ There is now a series of addins for going to a specific golem file (#212, @novica), and also to wrap a selected text into `ns()` (#143, @kokbent)
+- There is now a series of addins for going to a specific golem file (#212, @novica), and also to wrap a selected text into `ns()` (#143, @kokbent)
-+ Creation of a golem project is now a little bit more talkative (#63, @novica)
+- Creation of a golem project is now a little bit more talkative (#63, @novica)
-+ golem apps now have a title tag in the header by default, (#172, @novica)
+- golem apps now have a title tag in the header by default, (#172, @novica)
-+ The `rsconnect` folder is now added to `.Rbuildignore` (#244)
+- The `rsconnect` folder is now added to `.Rbuildignore` (#244)
-+ `devtools::test()` in 03_deploy.R is now `devtools::check()`
+- `devtools::test()` in 03_deploy.R is now `devtools::check()`
-+ modules bow have a placeholder for content
+- modules bow have a placeholder for content
-+ Dev scripts have been rewritten and rerordered a litte bit
+- Dev scripts have been rewritten and rerordered a litte bit
-## Breaking changes
+## Breaking changes
-+ `invoke_js()` now takes a list of elements to send to JS (through `...`) instead of a vector (#155, @zwycl)
+- `invoke_js()` now takes a list of elements to send to JS (through `...`) instead of a vector (#155, @zwycl)
-+ `get_dependencies` was removed from this package, please use `desc::desc_get_deps()` instead (#251)
+- `get_dependencies` was removed from this package, please use `desc::desc_get_deps()` instead (#251)
-+ `{golem}` now uses `here::here()` to determine the default working directory (#287)
+- `{golem}` now uses `here::here()` to determine the default working directory (#287)
-+ Modules used to be exported by default. You now have to specify it when creating the modules (#144)
+- Modules used to be exported by default. You now have to specify it when creating the modules (#144)
-+ `run_app()` is no longer explicitely namespaced in the run_dev script (#267)
+- `run_app()` is no longer explicitely namespaced in the run_dev script (#267)
-+ JavaScript files now default to having `$(document).ready()` (#227)
+- JavaScript files now default to having `$(document).ready()` (#227)
-+ Every filesystem manipulation is now done with `{fs}`. That should be pretty transparent for most users but please open an issue if it causes problem (#285)
+- Every filesystem manipulation is now done with `{fs}`. That should be pretty transparent for most users but please open an issue if it causes problem (#285)
## Bug fix
-+ The Dockerfile is now correctly added to .Rbuildignore (#81)
+- The Dockerfile is now correctly added to .Rbuildignore (#81)
-+ The dockerfile for shinyproxy no longer has a typo (#156, @fmmattioni)
+- The dockerfile for shinyproxy no longer has a typo (#156, @fmmattioni)
-+ `normalizePath()` now has a correct winlash (@kokbent)
+- `normalizePath()` now has a correct winlash (@kokbent)
-+ spellcheck in files (@privefl)
+- spellcheck in files (@privefl)
-+ Message to link to `golem_add_external_resources()` is now conditional to R being in a golem project (#167, @novica)
+- Message to link to `golem_add_external_resources()` is now conditional to R being in a golem project (#167, @novica)
-+ Better error on missing name in add_*, (#120, @novica)
+- Better error on missing name in add\_\*, (#120, @novica)
-+ When adding file, the extension is now ignored if provided by the user (#231)
+- When adding file, the extension is now ignored if provided by the user (#231)
-+ The dots R/run_app.R are now documented by default (#243)
+- The dots R/run_app.R are now documented by default (#243)
-+ Bug fix of the pkgdown website (#180)
+- Bug fix of the pkgdown website (#180)
-+ `{golem}` now correctly handles command line creation of projet inside the current directory (#248)
+- `{golem}` now correctly handles command line creation of projet inside the current directory (#248)
-+ The test are now more robust when it comes to random name generation (#281)
+- The test are now more robust when it comes to random name generation (#281)
## Internal changes
-+ We no longer depend on `{stringr}` (#201, @TomerPacific)
+- We no longer depend on `{stringr}` (#201, @TomerPacific)
-+ get_golem_wd() is now used everywhere in `{golem}` (#237, @felixgolcher)
+- get_golem_wd() is now used everywhere in `{golem}` (#237, @felixgolcher)
-# golem 0.1.0 - CRAN release candidate, v2
+# golem 0.1.0 - CRAN release candidate, v2
-## New Functions
+## New Functions
-+ `get_golem_wd` allows to print the current golem working directory, and `set_golem_wd` to change it.
+- `get_golem_wd` allows to print the current golem working directory, and `set_golem_wd` to change it.
-## Breaking changes
+## Breaking changes
-+ In order to work, the functions creating files need a `golem.wd`. This working directory is set by `set_golem_options` or the first time you create a file. It default to `"."`, the current directory.
+- In order to work, the functions creating files need a `golem.wd`. This working directory is set by `set_golem_options` or the first time you create a file. It default to `"."`, the current directory.
-+ Changes in the name of the args in `set_golem_options`: `pkg_path` is now `golem_wd`, `pkg_name` is now `golem_name`, `pkg_version` is now `golem_version`
+- Changes in the name of the args in `set_golem_options`: `pkg_path` is now `golem_wd`, `pkg_name` is now `golem_name`, `pkg_version` is now `golem_version`
## Internal changes
-+ The `installed.packages()` function is no longer used.
+- The `installed.packages()` function is no longer used.
-+ Every filesystem manipulation is now done with `{fs}` (#285)
+- Every filesystem manipulation is now done with `{fs}` (#285)
# golem 0.0.1.9999 - CRAN release candidate
## Changes in the way run_app and deploy files are build
-+ There is now a unique framework for run_app, that allows to deploy anywhere and can accept arguments. These arguments can then be retrieved with `get_golem_options()`.
+- There is now a unique framework for run_app, that allows to deploy anywhere and can accept arguments. These arguments can then be retrieved with `get_golem_options()`.
> See https://rtask.thinkr.fr/blog/shinyapp-runapp-shinyappdir-difference/
## Breaking Changes
-+ There is no need for `ui.R` and `server.R` to exist by default. Removed. Can be recreated with `add_ui_server_files()`
+- There is no need for `ui.R` and `server.R` to exist by default. Removed. Can be recreated with `add_ui_server_files()`
## New function
-+ There is now `add_shinyserver_file` & `add_shinyappsio_file`, #40
-+ `add_ui_server_files()` creates an ui & server.R files.
+- There is now `add_shinyserver_file` & `add_shinyappsio_file`, #40
+- `add_ui_server_files()` creates an ui & server.R files.
-## Small functions updates
+## Small functions updates
-+ Functions that create file(s) now automatically create folder if it's not there. Can be prevented with `dir_create = FALSE`
-+ Functions that create file(s) can now be prevented from opening with `open = FALSE`, #75
-+ We have made explicit how to add external files (css & js) to the app, #78
-+ Launch test is now included in the default tests #48
+- Functions that create file(s) now automatically create folder if it's not there. Can be prevented with `dir_create = FALSE`
+- Functions that create file(s) can now be prevented from opening with `open = FALSE`, #75
+- We have made explicit how to add external files (css & js) to the app, #78
+- Launch test is now included in the default tests #48
# golem 0.0.1.6000+
-## Changes
+## Changes
-* `create_golem()` now switch to the newly created project
-* `use_git()` is not listed in `dev/01_start.R`
+- `create_golem()` now switch to the newly created project
+- `use_git()` is not listed in `dev/01_start.R`
-## Breaking changes
+## Breaking changes
-* Renamed `add_rconnect_file()` to `add_rstudioconnect_file()`
-* Renamed `create_shiny_template()` to `create_golem()`
-* Renamed `js()` to `activate_js()`
-* Renamed `use_recommended_dep()` to `use_recommended_deps()`
+- Renamed `add_rconnect_file()` to `add_rstudioconnect_file()`
+- Renamed `create_shiny_template()` to `create_golem()`
+- Renamed `js()` to `activate_js()`
+- Renamed `use_recommended_dep()` to `use_recommended_deps()`
-## New functions
+## New functions
-* `invoke_js()` allows to call JS functions from the server side. #52
+- `invoke_js()` allows to call JS functions from the server side. #52
# golem 0.0.1.5000
-## Changes
+## Changes
-* The dev files are now split in three - start / dev / deploy
+- The dev files are now split in three - start / dev / deploy
-* Every function that adds a file now check if the file already exists, and ask the user if they want to overwrite it (#15)
+- Every function that adds a file now check if the file already exists, and ask the user if they want to overwrite it (#15)
-* Every module is now named mod_x_ui / mod_x_server, for consistency.
+- Every module is now named mod_x_ui / mod_x_server, for consistency.
-* You can now create package with "illegal" names, using the command line `golem::create_shiny_template()`. #18
+- You can now create package with "illegal" names, using the command line `golem::create_shiny_template()`. #18
-* `add_browser_button()` is now named `browser_button()`, so that all the `add_*` function are only reserved for function adding files to the `golem`.
+- `add_browser_button()` is now named `browser_button()`, so that all the `add_*` function are only reserved for function adding files to the `golem`.
-+ `add_*_files` now check if the folder exists, if not suggests to create it. #36
+* `add_*_files` now check if the folder exists, if not suggests to create it. #36
## New functions
-* You now have a `browser_dev()` function that behaves like `warning_dev` and friends. #46
+- You now have a `browser_dev()` function that behaves like `warning_dev` and friends. #46
-* Added `set_golem_options()` to add local options used internally by {golem} && added it to the `01_start.R`. #49
+- Added `set_golem_options()` to add local options used internally by {golem} && added it to the `01_start.R`. #49
-* Added `add_dockerfile()` to create a Dockerfile from a DESCRIPTION.
+- Added `add_dockerfile()` to create a Dockerfile from a DESCRIPTION.
-* Added `add_dockerfile_shinyproxy()` to create a Dockerfile from a DESCRIPTION, to be used in Shiny Proxy.
+- Added `add_dockerfile_shinyproxy()` to create a Dockerfile from a DESCRIPTION, to be used in Shiny Proxy.
-* Added `add_dockerfile_heroku()` to create a Dockerfile from a DESCRIPTION, to be used with Heroku.
+- Added `add_dockerfile_heroku()` to create a Dockerfile from a DESCRIPTION, to be used with Heroku.
-* `add_css_file()`, `add_js_file()` and `add_js_handler()` create a CSS, JS, and JS with Shiny custom handler files.
+- `add_css_file()`, `add_js_file()` and `add_js_handler()` create a CSS, JS, and JS with Shiny custom handler files.
## Removed
-* `use_utils_prod` is now included in golem so you don't have to explicitly include the functions.
+- `use_utils_prod` is now included in golem so you don't have to explicitly include the functions.
-## Docs
+## Docs
-* Golem now has four vignettes
+- Golem now has four vignettes
# golem 0.0.1.0002
@@ -426,6 +480,6 @@ Last round of functions, and some documentation cleanup.
# golem 0.0.0.9000
-* Moved from {shinytemplate} to {golem}
+- Moved from {shinytemplate} to {golem}
-* Added a `NEWS.md` file to track changes to the package.
+- Added a `NEWS.md` file to track changes to the package.
diff --git a/R/add_dockerfiles.R b/R/add_dockerfiles.R
index a94e9c00..5d1c54d5 100644
--- a/R/add_dockerfiles.R
+++ b/R/add_dockerfiles.R
@@ -1,7 +1,20 @@
+talk_once <- function(.f, msg = "") {
+ talk <- TRUE
+ function(...) {
+ if (talk) {
+ talk <<- FALSE
+ cat_red_bullet(msg)
+ }
+ .f(...)
+ }
+}
+
#' Create a Dockerfile for your App
#'
-#' Build a container containing your Shiny App. `add_dockerfile()` creates
-#' a generic Dockerfile, while `add_dockerfile_shinyproxy()` and
+#' Build a container containing your Shiny App. `add_dockerfile()` and
+#' `add_dockerfile_with_renv()` and `add_dockerfile_with_renv()` creates
+#' a generic Dockerfile, while `add_dockerfile_shinyproxy()`,
+#' `add_dockerfile_with_renv_shinyproxy()` , `add_dockerfile_with_renv_shinyproxy()` and
#' `add_dockerfile_heroku()` creates platform specific Dockerfile.
#'
#' @inheritParams add_module
@@ -9,288 +22,390 @@
#' @param path path to the DESCRIPTION file to use as an input.
#' @param output name of the Dockerfile output.
#' @param from The FROM of the Dockerfile. Default is
-#' FROM rocker/r-ver:`R.Version()$major`.`R.Version()$minor`.
+#'
+#' FROM rocker/verse
+#'
+#' without renv.lock file passed
+#' `R.Version()$major`.`R.Version()$minor` is used as tag
+#'
#' @param as The AS of the Dockerfile. Default it NULL.
#' @param port The `options('shiny.port')` on which to run the App.
#' Default is 80.
#' @param host The `options('shiny.host')` on which to run the App.
#' Default is 0.0.0.0.
-#' @param sysreqs boolean. If TRUE, the Dockerfile will contain sysreq installation.
+#' @param sysreqs boolean. If TRUE, RUN statements to install packages
+#' system requirements will be included in the Dockerfile.
#' @param repos character. The URL(s) of the repositories to use for `options("repos")`.
#' @param expand boolean. If `TRUE` each system requirement will have its own `RUN` line.
-#' @param open boolean. Should the Dockerfile be open after creation? Default is `TRUE`.
+#' @param open boolean. Should the Dockerfile/README/README be open after creation? Default is `TRUE`.
#' @param build_golem_from_source boolean. If `TRUE` no tar.gz is created and
#' the Dockerfile directly mount the source folder.
#' @param update_tar_gz boolean. If `TRUE` and `build_golem_from_source` is also `TRUE`,
#' an updated tar.gz is created.
#' @param extra_sysreqs character vector. Extra debian system requirements.
-#' Will be installed with apt-get install.
#'
#' @export
#' @rdname dockerfiles
#'
-#' @importFrom usethis use_build_ignore
-#' @importFrom desc desc_get_deps
-#' @importFrom rstudioapi navigateToFile isAvailable hasFun
-#' @importFrom fs path path_file
#'
#' @examples
#' \donttest{
#' # Add a standard Dockerfile
-#' if (interactive()) {
+#' if (interactive() & requireNamespace("dockerfiler")) {
#' add_dockerfile()
#' }
+#' # Crete a 'deploy' folder containing everything needed to deploy
+#' # the golem using docker based on {renv}
+#' if (interactive() & requireNamespace("dockerfiler")) {
+#' add_dockerfile_with_renv(
+#' # lockfile = "renv.lock", # uncomment to use existing renv.lock file
+#' output_dir = "deploy"
+#' )
+#' }
#' # Add a Dockerfile for ShinyProxy
-#' if (interactive()) {
+#' if (interactive() & requireNamespace("dockerfiler")) {
#' add_dockerfile_shinyproxy()
#' }
+#'
+#' # Crete a 'deploy' folder containing everything needed to deploy
+#' # the golem with ShinyProxy using docker based on {renv}
+#' if (interactive() & requireNamespace("dockerfiler")) {
+#' add_dockerfile_with_renv(
+#' # lockfile = "renv.lock",# uncomment to use existing renv.lock file
+#' output_dir = "deploy"
+#' )
+#' }
+#'
#' # Add a Dockerfile for Heroku
-#' if (interactive()) {
+#' if (interactive() & requireNamespace("dockerfiler")) {
#' add_dockerfile_heroku()
#' }
#' }
#' @return The `{dockerfiler}` object, invisibly.
add_dockerfile <- function(
- path = "DESCRIPTION",
- output = "Dockerfile",
- pkg = get_golem_wd(),
- from = paste0(
- "rocker/r-ver:",
- R.Version()$major,
- ".",
- R.Version()$minor
- ),
- as = NULL,
- port = 80,
- host = "0.0.0.0",
- sysreqs = TRUE,
- repos = c(CRAN = "https://cran.rstudio.com/"),
- expand = FALSE,
- open = TRUE,
- update_tar_gz = TRUE,
- build_golem_from_source = TRUE,
- extra_sysreqs = NULL
-) {
- rlang::check_installed(
- "dockerfiler",
- "to create Dockerfile using {golem}.",
- version = "0.1.4"
- )
-
- where <- path(pkg, output)
-
- usethis::use_build_ignore(path_file(where))
-
- dock <- dockerfiler::dock_from_desc(
+ path = "DESCRIPTION",
+ output = "Dockerfile",
+ pkg = get_golem_wd(),
+ from = paste0(
+ "rocker/verse:",
+ R.Version()$major,
+ ".",
+ R.Version()$minor
+ ),
+ as = NULL,
+ port = 80,
+ host = "0.0.0.0",
+ sysreqs = TRUE,
+ repos = c(CRAN = "https://cran.rstudio.com/"),
+ expand = FALSE,
+ open = TRUE,
+ update_tar_gz = TRUE,
+ build_golem_from_source = TRUE,
+ extra_sysreqs = NULL) {
+ add_dockerfile_(
path = path,
- FROM = from,
- AS = as,
+ output = output,
+ pkg = pkg,
+ from = from,
+ as = as,
+ port = port,
+ host = host,
sysreqs = sysreqs,
repos = repos,
expand = expand,
- build_from_source = build_golem_from_source,
+ open = open,
update_tar_gz = update_tar_gz,
+ build_golem_from_source = build_golem_from_source,
extra_sysreqs = extra_sysreqs
)
+}
- dock$EXPOSE(port)
+add_dockerfile_ <- talk_once(
+ function(
+ path = "DESCRIPTION",
+ output = "Dockerfile",
+ pkg = get_golem_wd(),
+ from = paste0(
+ "rocker/verse:",
+ R.Version()$major,
+ ".",
+ R.Version()$minor
+ ),
+ as = NULL,
+ port = 80,
+ host = "0.0.0.0",
+ sysreqs = TRUE,
+ repos = c(CRAN = "https://cran.rstudio.com/"),
+ expand = FALSE,
+ open = TRUE,
+ update_tar_gz = TRUE,
+ build_golem_from_source = TRUE,
+ extra_sysreqs = NULL) {
+ where <- fs_path(pkg, output)
- dock$CMD(
- sprintf(
- "R -e \"options('shiny.port'=%s,shiny.host='%s');%s::run_app()\"",
- port,
- host,
- read.dcf(path)[1]
+ usethis_use_build_ignore(
+ basename(where)
)
- )
- dock$write(output)
+ dock <- dockerfiler_dock_from_desc(
+ path = path,
+ FROM = from,
+ AS = as,
+ sysreqs = sysreqs,
+ repos = repos,
+ expand = expand,
+ build_from_source = build_golem_from_source,
+ update_tar_gz = update_tar_gz,
+ extra_sysreqs = extra_sysreqs
+ )
- if (open) {
- if (rstudioapi::isAvailable() & rstudioapi::hasFun("navigateToFile")) {
- rstudioapi::navigateToFile(output)
- } else {
- try(file.edit(output))
+ dock$EXPOSE(port)
+
+ dock$CMD(
+ sprintf(
+ "R -e \"options('shiny.port'=%s,shiny.host='%s');library(%3$s);%3$s::run_app()\"",
+ port,
+ host,
+ read.dcf(path)[1]
+ )
+ )
+
+ dock$write(output)
+
+ if (open) {
+ rstudioapi_navigateToFile(output)
}
- }
- alert_build(
- path = path,
- output = output,
- build_golem_from_source = build_golem_from_source
- )
+ alert_build(
+ path = path,
+ output = output,
+ build_golem_from_source = build_golem_from_source
+ )
- return(invisible(dock))
-}
+ return(invisible(dock))
+ },
+ "golem::add_dockerfile() is not recommended anymore.\nPlease use golem::add_dockerfile_with_renv() instead."
+)
#' @export
#' @rdname dockerfiles
-#' @importFrom fs path path_file
add_dockerfile_shinyproxy <- function(
- path = "DESCRIPTION",
- output = "Dockerfile",
- pkg = get_golem_wd(),
- from = paste0(
- "rocker/r-ver:",
- R.Version()$major,
- ".",
- R.Version()$minor
- ),
- as = NULL,
- sysreqs = TRUE,
- repos = c(CRAN = "https://cran.rstudio.com/"),
- expand = FALSE,
- open = TRUE,
- update_tar_gz = TRUE,
- build_golem_from_source = TRUE,
- extra_sysreqs = NULL
-) {
- rlang::check_installed(
- "dockerfiler",
- "to create Dockerfile using {golem}.",
- version = "0.1.4"
- )
-
- where <- path(pkg, output)
-
- usethis::use_build_ignore(output)
-
- dock <- dockerfiler::dock_from_desc(
+ path = "DESCRIPTION",
+ output = "Dockerfile",
+ pkg = get_golem_wd(),
+ from = paste0(
+ "rocker/verse:",
+ R.Version()$major,
+ ".",
+ R.Version()$minor
+ ),
+ as = NULL,
+ sysreqs = TRUE,
+ repos = c(CRAN = "https://cran.rstudio.com/"),
+ expand = FALSE,
+ open = TRUE,
+ update_tar_gz = TRUE,
+ build_golem_from_source = TRUE,
+ extra_sysreqs = NULL) {
+ add_dockerfile_shinyproxy_(
path = path,
- FROM = from,
- AS = as,
+ output = output,
+ pkg = pkg,
+ from = from,
+ as = as,
sysreqs = sysreqs,
repos = repos,
expand = expand,
- build_from_source = build_golem_from_source,
+ open = open,
update_tar_gz = update_tar_gz,
+ build_golem_from_source = build_golem_from_source,
extra_sysreqs = extra_sysreqs
)
+}
- dock$EXPOSE(3838)
- dock$CMD(sprintf(
- " [\"R\", \"-e\", \"options('shiny.port'=3838,shiny.host='0.0.0.0');%s::run_app()\"]",
- read.dcf(path)[1]
- ))
- dock$write(output)
+add_dockerfile_shinyproxy_ <- talk_once(
+ function(
+ path = "DESCRIPTION",
+ output = "Dockerfile",
+ pkg = get_golem_wd(),
+ from = paste0(
+ "rocker/verse:",
+ R.Version()$major,
+ ".",
+ R.Version()$minor
+ ),
+ as = NULL,
+ sysreqs = TRUE,
+ repos = c(CRAN = "https://cran.rstudio.com/"),
+ expand = FALSE,
+ open = TRUE,
+ update_tar_gz = TRUE,
+ build_golem_from_source = TRUE,
+ extra_sysreqs = NULL) {
+ where <- fs_path(pkg, output)
+
+ usethis_use_build_ignore(output)
+
+ dock <- dockerfiler_dock_from_desc(
+ path = path,
+ FROM = from,
+ AS = as,
+ sysreqs = sysreqs,
+ repos = repos,
+ expand = expand,
+ build_from_source = build_golem_from_source,
+ update_tar_gz = update_tar_gz,
+ extra_sysreqs = extra_sysreqs
+ )
+
+ dock$EXPOSE(3838)
+ dock$CMD(sprintf(
+ " [\"R\", \"-e\", \"options('shiny.port'=3838,shiny.host='0.0.0.0');library(%1$s);%1$s::run_app()\"]",
+ read.dcf(path)[1]
+ ))
+ dock$write(output)
- if (open) {
- if (rstudioapi::isAvailable() & rstudioapi::hasFun("navigateToFile")) {
- rstudioapi::navigateToFile(output)
- } else {
- try(file.edit(output))
+ if (open) {
+ rstudioapi_navigateToFile(output)
}
- }
- alert_build(
- path,
- output,
- build_golem_from_source = build_golem_from_source
- )
+ alert_build(
+ path,
+ output,
+ build_golem_from_source = build_golem_from_source
+ )
- return(invisible(dock))
-}
+ return(invisible(dock))
+ },
+ "golem::add_dockerfile_shinyproxy() is not recommended anymore.\nPlease use golem::add_dockerfile_with_renv_shinyproxy() instead."
+)
#' @export
#' @rdname dockerfiles
-#' @importFrom fs path path_file
add_dockerfile_heroku <- function(
- path = "DESCRIPTION",
- output = "Dockerfile",
- pkg = get_golem_wd(),
- from = paste0(
- "rocker/r-ver:",
- R.Version()$major,
- ".",
- R.Version()$minor
- ),
- as = NULL,
- sysreqs = TRUE,
- repos = c(CRAN = "https://cran.rstudio.com/"),
- expand = FALSE,
- open = TRUE,
- update_tar_gz = TRUE,
- build_golem_from_source = TRUE,
- extra_sysreqs = NULL
-) {
- rlang::check_installed(
- "dockerfiler",
- "to create Dockerfile using {golem}.",
- version = "0.1.4"
- )
-
- where <- path(pkg, output)
-
- usethis::use_build_ignore(output)
-
- dock <- dockerfiler::dock_from_desc(
+ path = "DESCRIPTION",
+ output = "Dockerfile",
+ pkg = get_golem_wd(),
+ from = paste0(
+ "rocker/verse:",
+ R.Version()$major,
+ ".",
+ R.Version()$minor
+ ),
+ as = NULL,
+ sysreqs = TRUE,
+ repos = c(CRAN = "https://cran.rstudio.com/"),
+ expand = FALSE,
+ open = TRUE,
+ update_tar_gz = TRUE,
+ build_golem_from_source = TRUE,
+ extra_sysreqs = NULL) {
+ add_dockerfile_heroku_(
path = path,
- FROM = from,
- AS = as,
+ output = output,
+ pkg = pkg,
+ from = from,
+ as = as,
sysreqs = sysreqs,
repos = repos,
expand = expand,
- build_from_source = build_golem_from_source,
+ open = open,
update_tar_gz = update_tar_gz,
+ build_golem_from_source = build_golem_from_source,
extra_sysreqs = extra_sysreqs
)
+}
- dock$CMD(
- sprintf(
- "R -e \"options('shiny.port'=$PORT,shiny.host='0.0.0.0');%s::run_app()\"",
- read.dcf(path)[1]
+add_dockerfile_heroku_ <- talk_once(
+ function(
+ path = "DESCRIPTION",
+ output = "Dockerfile",
+ pkg = get_golem_wd(),
+ from = paste0(
+ "rocker/verse:",
+ R.Version()$major,
+ ".",
+ R.Version()$minor
+ ),
+ as = NULL,
+ sysreqs = TRUE,
+ repos = c(CRAN = "https://cran.rstudio.com/"),
+ expand = FALSE,
+ open = TRUE,
+ update_tar_gz = TRUE,
+ build_golem_from_source = TRUE,
+ extra_sysreqs = NULL) {
+ where <- fs_path(pkg, output)
+
+ usethis_use_build_ignore(output)
+
+ dock <- dockerfiler_dock_from_desc(
+ path = path,
+ FROM = from,
+ AS = as,
+ sysreqs = sysreqs,
+ repos = repos,
+ expand = expand,
+ build_from_source = build_golem_from_source,
+ update_tar_gz = update_tar_gz,
+ extra_sysreqs = extra_sysreqs
)
- )
- dock$write(output)
- alert_build(
- path = path,
- output = output,
- build_golem_from_source = build_golem_from_source
- )
+ dock$CMD(
+ sprintf(
+ "R -e \"options('shiny.port'=$PORT,shiny.host='0.0.0.0');library(%1$s);%1$s::run_app()\"",
+ read.dcf(path)[1]
+ )
+ )
+ dock$write(output)
- apps_h <- gsub(
- "\\.",
- "-",
- sprintf(
- "%s-%s",
- read.dcf(path)[1],
- read.dcf(path)[1, ][["Version"]]
+ alert_build(
+ path = path,
+ output = output,
+ build_golem_from_source = build_golem_from_source
)
- )
- cat_rule("From your command line, run:")
- cat_line("heroku container:login")
- cat_line(
- sprintf("heroku create %s", apps_h)
- )
- cat_line(
- sprintf("heroku container:push web --app %s", apps_h)
- )
- cat_line(
- sprintf("heroku container:release web --app %s", apps_h)
- )
- cat_line(
- sprintf("heroku open --app %s", apps_h)
- )
- cat_red_bullet("Be sure to have the heroku CLI installed.")
- cat_red_bullet(
- sprintf("You can replace %s with another app name.", apps_h)
- )
- if (open) {
- if (rstudioapi::isAvailable() & rstudioapi::hasFun("navigateToFile")) {
- rstudioapi::navigateToFile(output)
- } else {
- try(file.edit(output))
+ apps_h <- gsub(
+ "\\.",
+ "-",
+ sprintf(
+ "%s-%s",
+ read.dcf(path)[1],
+ read.dcf(path)[1, ][["Version"]]
+ )
+ )
+
+ cli_cat_rule("From your command line, run:")
+ cli_cat_line("heroku container:login")
+ cli_cat_line(
+ sprintf("heroku create %s", apps_h)
+ )
+ cli_cat_line(
+ sprintf("heroku container:push web --app %s", apps_h)
+ )
+ cli_cat_line(
+ sprintf("heroku container:release web --app %s", apps_h)
+ )
+ cli_cat_line(
+ sprintf("heroku open --app %s", apps_h)
+ )
+ cat_red_bullet("Be sure to have the heroku CLI installed.")
+ cat_red_bullet(
+ sprintf("You can replace %s with another app name.", apps_h)
+ )
+ if (open) {
+ rstudioapi_navigateToFile(output)
}
- }
- usethis::use_build_ignore(files = output)
- return(invisible(dock))
-}
+ usethis_use_build_ignore(files = output)
+ return(invisible(dock))
+ },
+ "
+golem::add_dockerfile_heroku() is not recommended anymore.\nPlease use golem::add_dockerfile_with_renv_heroku() instead.
+"
+)
alert_build <- function(
- path,
- output,
- build_golem_from_source
-) {
+ path,
+ output,
+ build_golem_from_source) {
cat_created(output, "Dockerfile")
if (!build_golem_from_source) {
cat_red_bullet(
diff --git a/R/add_dockerfiles_renv.R b/R/add_dockerfiles_renv.R
new file mode 100644
index 00000000..24afc09f
--- /dev/null
+++ b/R/add_dockerfiles_renv.R
@@ -0,0 +1,374 @@
+add_dockerfile_with_renv_ <- function(
+ source_folder = ".",
+ lockfile = NULL,
+ output_dir = fs::path(tempdir(), "deploy"),
+ distro = "focal",
+ FROM = "rocker/verse",
+ AS = NULL,
+ sysreqs = TRUE,
+ repos = c(CRAN = "https://cran.rstudio.com/"),
+ expand = FALSE,
+ extra_sysreqs = NULL,
+ update_tar_gz = TRUE,
+ document = FALSE,
+ ...
+ # build_golem_from_source = TRUE,
+ ) {
+ if (is.null(lockfile)) {
+ rlang::check_installed(
+ c("renv", "attachment"),
+ reason = "to build a Dockerfile with automatic renv.lock creation. Use the `lockfile` parameter to pass your own `renv.lock` file."
+ )
+ }
+
+
+ # Small hack to prevent warning from rlang::lang() in tests
+ # This should be managed in {attempt} later on
+ x <- suppressWarnings({
+ rlang::lang(print)
+ })
+
+ dir.create(output_dir)
+
+ # add output_dir in Rbuildignore if the output is inside the golem
+ if (normalizePath(dirname(output_dir)) == normalizePath(source_folder)) {
+ usethis_use_build_ignore(output_dir)
+ }
+
+ if (is.null(lockfile)) {
+ if (isTRUE(document)) {
+ cli_cat_line("You set `document = TRUE` and you did not pass your own renv.lock file,")
+ cli_cat_line("as a consequence {golem} will use `attachment::att_amend_desc()` to update your ")
+ cli_cat_line("DESCRIPTION file before creating the renv.lock file")
+ cli_cat_line("")
+ cli_cat_line("you can set `document = FALSE` to use your actual DESCRIPTION file,")
+ cli_cat_line("or pass you own renv.lock to use, using the `lockfile` parameter")
+ cli_cat_line("")
+ cli_cat_line("In any case be sure to have no Error or Warning at `devtools::check()`")
+ }
+
+
+
+
+ lockfile <- attachment_create_renv_for_prod(
+ path = source_folder,
+ check_if_suggests_is_installed = FALSE, document = document,
+ output = file.path(output_dir, "renv.lock.prod"),
+ ...
+ )
+ }
+
+ # fs_file_copy(
+ # path = lockfile,
+ # new_path = output_dir,
+ # overwrite = TRUE
+ # )
+ file.copy(from = lockfile, to = output_dir)
+ socle <- dockerfiler::dock_from_renv(
+ lockfile = lockfile,
+ distro = distro,
+ FROM = FROM,
+ repos = repos,
+ AS = AS,
+ sysreqs = sysreqs,
+ expand = expand,
+ extra_sysreqs = extra_sysreqs
+ )
+
+ socle$write(as = file.path(output_dir, "Dockerfile_base"))
+
+
+ my_dock <- dockerfiler_Dockerfile()$new(FROM = tolower(tolower(paste0(golem::get_golem_name(), "_base"))))
+
+ my_dock$COPY("renv.lock.prod", "renv.lock")
+
+ my_dock$RUN("R -e 'renv::restore()'")
+
+ if (update_tar_gz) {
+ old_version <- list.files(path = output_dir, pattern = paste0(golem::get_golem_name(), "_*.*.tar.gz"), full.names = TRUE)
+ # file.remove(old_version)
+ if (length(old_version) > 0) {
+ lapply(old_version, file.remove)
+ lapply(old_version, unlink, force = TRUE)
+ cat_red_bullet(
+ sprintf(
+ "%s were removed from folder",
+ paste(
+ old_version,
+ collapse = ", "
+ )
+ )
+ )
+ }
+
+ if (
+ isTRUE(
+ requireNamespace(
+ "pkgbuild",
+ quietly = TRUE
+ )
+ )
+ ) {
+ out <- pkgbuild::build(
+ path = ".",
+ dest_path = output_dir,
+ vignettes = FALSE
+ )
+ if (missing(out)) {
+ cat_red_bullet("Error during tar.gz building")
+ } else {
+ cat_green_tick(
+ sprintf(
+ " %s created.",
+ out
+ )
+ )
+ }
+ } else {
+ stop("please install {pkgbuild}")
+ }
+ }
+
+ # we use an already built tar.gz file
+ my_dock$COPY(
+ from =
+ paste0(golem::get_golem_name(), "_*.tar.gz"),
+ to = "/app.tar.gz"
+ )
+ my_dock$RUN("R -e 'remotes::install_local(\"/app.tar.gz\",upgrade=\"never\")'")
+ my_dock$RUN("rm /app.tar.gz")
+ my_dock
+}
+
+#' @param source_folder path to the Package/golem source folder to deploy.
+#' default is current folder '.'
+#' @param lockfile path to the renv.lock file to use. default is `NULL`
+#' @param output_dir folder to export everything deployment related.
+#' @param distro One of "focal", "bionic", "xenial", "centos7", or "centos8".
+#' See available distributions at https://hub.docker.com/r/rstudio/r-base/.
+#' @param document boolean. If TRUE (by default), DESCRIPTION file is updated using [attachment::att_amend_desc()] before creating the renv.lock file
+#' @param dockerfile_cmd What is the CMD to add to the Dockerfile. If NULL, the default,
+#' the CMD will be `R -e "options('shiny.port'={port},shiny.host='{host}');library({appname});{appname}::run_app()\`
+#' @param ... Other arguments to pass to [renv::snapshot()]
+#' @inheritParams add_dockerfile
+#' @rdname dockerfiles
+#' @export
+add_dockerfile_with_renv <- function(
+ source_folder = ".",
+ lockfile = NULL,
+ output_dir = fs::path(tempdir(), "deploy"),
+ distro = "focal",
+ from = "rocker/verse",
+ as = NULL,
+ sysreqs = TRUE,
+ port = 80,
+ host = "0.0.0.0",
+ repos = c(CRAN = "https://cran.rstudio.com/"),
+ expand = FALSE,
+ open = TRUE,
+ document = TRUE,
+ extra_sysreqs = NULL,
+ update_tar_gz = TRUE,
+ dockerfile_cmd = NULL,
+ ...) {
+ base_dock <- add_dockerfile_with_renv_(
+ source_folder = source_folder,
+ lockfile = lockfile,
+ output_dir = output_dir,
+ distro = distro,
+ FROM = from,
+ AS = as,
+ sysreqs = sysreqs,
+ repos = repos,
+ expand = expand,
+ extra_sysreqs = extra_sysreqs,
+ update_tar_gz = update_tar_gz,
+ document = document,
+ ...
+ )
+ if (!is.null(port)) {
+ base_dock$EXPOSE(port)
+ }
+ if (is.null(dockerfile_cmd)) {
+ dockerfile_cmd <- sprintf(
+ "R -e \"options('shiny.port'=%s,shiny.host='%s');library(%3$s);%3$s::run_app()\"",
+ port,
+ host,
+ golem::get_golem_name()
+ )
+ }
+ base_dock$CMD(
+ dockerfile_cmd
+ )
+ base_dock
+ base_dock$write(as = file.path(output_dir, "Dockerfile"))
+
+ out <- sprintf(
+ "docker build -f Dockerfile_base --progress=plain -t %s .
+docker build -f Dockerfile --progress=plain -t %s .
+docker run -p %s:%s %s
+# then go to 127.0.0.1:%s",
+ tolower(paste0(golem::get_golem_name(), "_base")),
+ tolower(paste0(golem::get_golem_name(), ":latest")),
+ port,
+ port,
+ tolower(paste0(golem::get_golem_name(), ":latest")),
+ port
+ )
+
+ cat(out, file = file.path(output_dir, "README"))
+
+ open_or_go_to(
+ where = file.path(output_dir, "README"),
+ open_file = open
+ )
+}
+
+#' @inheritParams add_dockerfile_with_renv
+#' @rdname dockerfiles
+#' @export
+#' @export
+add_dockerfile_with_renv_shinyproxy <- function(
+ source_folder = ".",
+ lockfile = NULL,
+ output_dir = fs::path(tempdir(), "deploy"),
+ distro = "focal",
+ from = "rocker/verse",
+ as = NULL,
+ sysreqs = TRUE,
+ repos = c(CRAN = "https://cran.rstudio.com/"),
+ expand = FALSE,
+ extra_sysreqs = NULL,
+ open = TRUE,
+ document = TRUE,
+ update_tar_gz = TRUE,
+ ...) {
+ add_dockerfile_with_renv(
+ source_folder = source_folder,
+ lockfile = lockfile,
+ output_dir = output_dir,
+ distro = distro,
+ from = from,
+ as = as,
+ sysreqs = sysreqs,
+ repos = repos,
+ expand = expand,
+ port = 3838,
+ host = "0.0.0.0",
+ extra_sysreqs = extra_sysreqs,
+ update_tar_gz = update_tar_gz,
+ open = open,
+ document = document,
+ dockerfile_cmd = sprintf(
+ "R -e \"options('shiny.port'=3838,shiny.host='0.0.0.0');library(%1$s);%1$s::run_app()\"",
+ golem::get_golem_name()
+ ),
+ ...
+ )
+}
+
+#' @inheritParams add_dockerfile_with_renv
+#' @rdname dockerfiles
+#' @export
+#' @export
+add_dockerfile_with_renv_heroku <- function(
+ source_folder = ".",
+ lockfile = NULL,
+ output_dir = fs::path(tempdir(), "deploy"),
+ distro = "focal",
+ from = "rocker/verse",
+ as = NULL,
+ sysreqs = TRUE,
+ repos = c(CRAN = "https://cran.rstudio.com/"),
+ expand = FALSE,
+ extra_sysreqs = NULL,
+ open = TRUE,
+ document = TRUE,
+ update_tar_gz = TRUE,
+ ...) {
+ add_dockerfile_with_renv(
+ source_folder = source_folder,
+ lockfile = lockfile,
+ output_dir = output_dir,
+ distro = distro,
+ from = from,
+ as = as,
+ sysreqs = sysreqs,
+ repos = repos,
+ expand = expand,
+ port = NULL,
+ host = "0.0.0.0",
+ extra_sysreqs = extra_sysreqs,
+ update_tar_gz = update_tar_gz,
+ open = FALSE,
+ document = document,
+ dockerfile_cmd = sprintf(
+ "R -e \"options('shiny.port'=$PORT,shiny.host='0.0.0.0');library(%1$s);%1$s::run_app()\"",
+ golem::get_golem_name()
+ ),
+ ...
+ )
+
+ apps_h <- gsub(
+ "\\.",
+ "-",
+ sprintf(
+ "%s-%s",
+ golem::get_golem_name(),
+ golem::get_golem_version()
+ )
+ )
+
+ readme_output <- fs_path(
+ output_dir,
+ "README"
+ )
+
+ write_there <- function(...) {
+ write(..., file = readme_output, append = TRUE)
+ }
+
+ write_there("From your command line, run:\n")
+
+ write_there(
+ sprintf(
+ "docker build -f Dockerfile_base --progress=plain -t %s .",
+ paste0(golem::get_golem_name(), "_base")
+ )
+ )
+
+ write_there(
+ sprintf(
+ "docker build -f Dockerfile --progress=plain -t %s .\n",
+ paste0(golem::get_golem_name(), ":latest")
+ )
+ )
+
+ write_there("Then, to push on heroku:\n")
+
+ write_there("heroku container:login")
+ write_there(
+ sprintf("heroku create %s", apps_h)
+ )
+ write_there(
+ sprintf("heroku container:push web --app %s", apps_h)
+ )
+ write_there(
+ sprintf("heroku container:release web --app %s", apps_h)
+ )
+ write_there(
+ sprintf("heroku open --app %s\n", apps_h)
+ )
+ write_there("> Be sure to have the heroku CLI installed.")
+
+ write_there(
+ sprintf("> You can replace %s with another app name.", apps_h)
+ )
+
+ # The open is deported here just to be sure
+ # That we open the README once it has been populated
+ open_or_go_to(
+ where = readme_output,
+ open_file = open
+ )
+}
diff --git a/R/add_files.R b/R/add_files.R
index bfe88086..663cdd2d 100644
--- a/R/add_files.R
+++ b/R/add_files.R
@@ -22,9 +22,7 @@
#' @export
#' @rdname add_files
#' @importFrom attempt stop_if
-#' @importFrom cli cat_bullet
#' @importFrom utils file.edit
-#' @importFrom fs path_abs path file_create file_exists
#'
#' @note `add_ui_server_files` will be deprecated in future version of `{golem}`
#'
@@ -43,12 +41,14 @@ add_js_file <- function(
) {
stop_if(
missing(name),
- msg = "Name is required"
+ msg = "`name` is required"
)
+ check_name_length(name)
+
name <- file_path_sans_ext(name)
- old <- setwd(path_abs(pkg))
+ old <- setwd(fs_path_abs(pkg))
on.exit(setwd(old))
dir_created <- create_if_needed(
@@ -61,16 +61,15 @@ add_js_file <- function(
return(invisible(FALSE))
}
- dir <- path_abs(dir)
+ dir <- fs_path_abs(dir)
- where <- path(
+ where <- fs_path(
dir,
sprintf("%s.js", name)
)
- if (!file.exists(where)) {
- file_create(where)
-
+ if (!fs_file_exists(where)) {
+ fs_file_create(where)
if (with_doc_ready) {
write_there <- function(...) {
write(..., file = where, append = TRUE)
@@ -99,8 +98,6 @@ add_js_file <- function(
#' @export
#' @rdname add_files
-#'
-#' @importFrom fs path_abs path file_create file_exists
add_js_handler <- function(
name,
pkg = get_golem_wd(),
@@ -112,12 +109,14 @@ add_js_handler <- function(
) {
attempt::stop_if(
missing(name),
- msg = "Name is required"
+ msg = "`name` is required"
)
+ check_name_length(name)
+
name <- file_path_sans_ext(name)
- old <- setwd(path_abs(pkg))
+ old <- setwd(fs_path_abs(pkg))
on.exit(setwd(old))
dir_created <- create_if_needed(
@@ -130,15 +129,15 @@ add_js_handler <- function(
return(invisible(FALSE))
}
- dir <- path_abs(dir)
+ dir <- fs_path_abs(dir)
- where <- file.path(
+ where <- fs_path(
dir,
sprintf("%s.js", name)
)
- if (!file.exists(where)) {
- file_create(where)
+ if (!fs_file_exists(where)) {
+ fs_file_create(where)
template(path = where, ...)
@@ -160,7 +159,6 @@ add_js_handler <- function(
#' @export
#' @rdname add_files
-#' @importFrom fs path_abs path file_create file_exists
add_js_input_binding <- function(
name,
pkg = get_golem_wd(),
@@ -176,9 +174,11 @@ add_js_input_binding <- function(
) {
attempt::stop_if(
missing(name),
- msg = "Name is required"
+ msg = "`name` is required"
)
+ check_name_length(name)
+
attempt::stop_if(
length(events$name) == 0,
msg = "At least one event is required"
@@ -195,7 +195,7 @@ add_js_input_binding <- function(
sprintf("input-%s", name)
)
- old <- setwd(path_abs(pkg))
+ old <- setwd(fs_path_abs(pkg))
on.exit(setwd(old))
dir_created <- create_if_needed(
@@ -208,15 +208,15 @@ add_js_input_binding <- function(
return(invisible(FALSE))
}
- dir <- path_abs(dir)
+ dir <- fs_path_abs(dir)
- where <- file.path(
+ where <- fs_path(
dir,
sprintf("%s.js", name)
)
- if (!file.exists(where)) {
- file_create(where)
+ if (!fs_file_exists(where)) {
+ fs_file_create(where)
write_there <- function(...) {
write(..., file = where, append = TRUE)
@@ -307,7 +307,6 @@ add_js_input_binding <- function(
#' @export
#' @rdname add_files
-#' @importFrom fs path_abs path file_create file_exists
add_js_output_binding <- function(
name,
pkg = get_golem_wd(),
@@ -317,16 +316,18 @@ add_js_output_binding <- function(
) {
attempt::stop_if(
missing(name),
- msg = "Name is required"
+ msg = "`name` is required"
)
+ check_name_length(name)
+
raw_name <- name
name <- file_path_sans_ext(
sprintf("output-%s", name)
)
- old <- setwd(path_abs(pkg))
+ old <- setwd(fs_path_abs(pkg))
on.exit(setwd(old))
dir_created <- create_if_needed(
@@ -339,15 +340,15 @@ add_js_output_binding <- function(
return(invisible(FALSE))
}
- dir <- path_abs(dir)
+ dir <- fs_path_abs(dir)
- where <- file.path(
+ where <- fs_path(
dir,
sprintf("%s.js", name)
)
- if (!file.exists(where)) {
- file_create(where)
+ if (!fs_file_exists(where)) {
+ fs_file_create(where)
write_there <- function(...) {
write(..., file = where, append = TRUE)
@@ -388,7 +389,6 @@ add_js_output_binding <- function(
#' @export
#' @rdname add_files
-#' @importFrom fs path_abs path file_create file_exists
add_css_file <- function(
name,
pkg = get_golem_wd(),
@@ -400,12 +400,14 @@ add_css_file <- function(
) {
attempt::stop_if(
missing(name),
- msg = "Name is required"
+ msg = "`name` is required"
)
+ check_name_length(name)
+
name <- file_path_sans_ext(name)
- old <- setwd(path_abs(pkg))
+ old <- setwd(fs_path_abs(pkg))
on.exit(setwd(old))
dir_created <- create_if_needed(
@@ -418,9 +420,9 @@ add_css_file <- function(
return(invisible(FALSE))
}
- dir <- path_abs(dir)
+ dir <- fs_path_abs(dir)
- where <- path(
+ where <- fs_path(
dir,
sprintf(
"%s.css",
@@ -428,8 +430,8 @@ add_css_file <- function(
)
)
- if (!file_exists(where)) {
- file_create(where)
+ if (!fs_file_exists(where)) {
+ fs_file_create(where)
template(path = where, ...)
file_created_dance(
where,
@@ -449,8 +451,6 @@ add_css_file <- function(
#' @export
#' @rdname add_files
-#' @importFrom fs path_abs path file_create file_exists
-#' @importFrom cli cli_alert_info
add_sass_file <- function(
name,
pkg = get_golem_wd(),
@@ -462,12 +462,14 @@ add_sass_file <- function(
) {
attempt::stop_if(
missing(name),
- msg = "Name is required"
+ msg = "`name` is required"
)
+ check_name_length(name)
+
name <- file_path_sans_ext(name)
- old <- setwd(path_abs(pkg))
+ old <- setwd(fs_path_abs(pkg))
on.exit(setwd(old))
dir_created <- create_if_needed(
@@ -480,9 +482,9 @@ add_sass_file <- function(
return(invisible(FALSE))
}
- dir_abs <- path_abs(dir)
+ dir_abs <- fs_path_abs(dir)
- where <- path(
+ where <- fs_path(
dir_abs,
sprintf(
"%s.sass",
@@ -490,8 +492,8 @@ add_sass_file <- function(
)
)
- if (!file_exists(where)) {
- file_create(where)
+ if (!fs_file_exists(where)) {
+ fs_file_create(where)
template(path = where, ...)
file_created_dance(
where,
@@ -502,9 +504,13 @@ add_sass_file <- function(
open
)
- add_sass_code(where = where, dir = dir, name = name)
+ add_sass_code(
+ where = where,
+ dir = dir,
+ name = name
+ )
- cli_alert_info(
+ cat_green_tick(
"After running the compilation, your CSS file will be automatically link in `golem_add_external_resources()`."
)
} else {
@@ -517,7 +523,6 @@ add_sass_file <- function(
#' @export
#' @rdname add_files
-#' @importFrom fs path_abs path file_create file_exists
add_html_template <- function(
name = "template.html",
pkg = get_golem_wd(),
@@ -527,7 +532,9 @@ add_html_template <- function(
) {
name <- file_path_sans_ext(name)
- old <- setwd(path_abs(pkg))
+ check_name_length(name)
+
+ old <- setwd(fs_path_abs(pkg))
on.exit(setwd(old))
dir_created <- create_if_needed(
@@ -540,9 +547,9 @@ add_html_template <- function(
return(invisible(FALSE))
}
- dir <- path_abs(dir)
+ dir <- fs_path_abs(dir)
- where <- path(
+ where <- fs_path(
dir,
sprintf(
"%s.html",
@@ -550,8 +557,8 @@ add_html_template <- function(
)
)
- if (!file_exists(where)) {
- file_create(where)
+ if (!fs_file_exists(where)) {
+ fs_file_create(where)
write_there <- function(...) write(..., file = where, append = TRUE)
write_there("")
write_there("")
@@ -584,10 +591,66 @@ add_html_template <- function(
}
}
+#' @export
+#' @rdname add_files
+add_partial_html_template <- function(
+ name = "partial_template.html",
+ pkg = get_golem_wd(),
+ dir = "inst/app/www",
+ open = TRUE,
+ dir_create = TRUE
+) {
+ name <- file_path_sans_ext(name)
+ check_name_length(name)
+
+ old <- setwd(fs_path_abs(pkg))
+ on.exit(setwd(old))
+
+ dir_created <- create_if_needed(
+ dir,
+ type = "directory"
+ )
+
+ if (!dir_created) {
+ cat_dir_necessary()
+ return(invisible(FALSE))
+ }
+
+ dir <- fs_path_abs(dir)
+
+ where <- fs_path(
+ dir,
+ sprintf(
+ "%s.html",
+ name
+ )
+ )
+
+ if (!fs_file_exists(where)) {
+ fs_file_create(where)
+ write_there <- function(...) write(..., file = where, append = TRUE)
+ write_there("
}}\preformatted{FROM rocker/verse
+
+without renv.lock file passed
+`R.Version()$major`.`R.Version()$minor` is used as tag
+}\if{html}{\out{
}}}
\item{as}{The AS of the Dockerfile. Default it NULL.}
@@ -71,13 +133,14 @@ Default is 80.}
\item{host}{The \code{options('shiny.host')} on which to run the App.
Default is 0.0.0.0.}
-\item{sysreqs}{boolean. If TRUE, the Dockerfile will contain sysreq installation.}
+\item{sysreqs}{boolean. If TRUE, RUN statements to install packages
+system requirements will be included in the Dockerfile.}
\item{repos}{character. The URL(s) of the repositories to use for \code{options("repos")}.}
\item{expand}{boolean. If \code{TRUE} each system requirement will have its own \code{RUN} line.}
-\item{open}{boolean. Should the Dockerfile be open after creation? Default is \code{TRUE}.}
+\item{open}{boolean. Should the Dockerfile/README/README be open after creation? Default is \code{TRUE}.}
\item{update_tar_gz}{boolean. If \code{TRUE} and \code{build_golem_from_source} is also \code{TRUE},
an updated tar.gz is created.}
@@ -85,29 +148,65 @@ an updated tar.gz is created.}
\item{build_golem_from_source}{boolean. If \code{TRUE} no tar.gz is created and
the Dockerfile directly mount the source folder.}
-\item{extra_sysreqs}{character vector. Extra debian system requirements.
-Will be installed with apt-get install.}
+\item{extra_sysreqs}{character vector. Extra debian system requirements.}
+
+\item{source_folder}{path to the Package/golem source folder to deploy.
+default is current folder '.'}
+
+\item{lockfile}{path to the renv.lock file to use. default is \code{NULL}}
+
+\item{output_dir}{folder to export everything deployment related.}
+
+\item{distro}{One of "focal", "bionic", "xenial", "centos7", or "centos8".
+See available distributions at https://hub.docker.com/r/rstudio/r-base/.}
+
+\item{document}{boolean. If TRUE (by default), DESCRIPTION file is updated using \code{\link[attachment:att_amend_desc]{attachment::att_amend_desc()}} before creating the renv.lock file}
+
+\item{dockerfile_cmd}{What is the CMD to add to the Dockerfile. If NULL, the default,
+the CMD will be \verb{R -e "options('shiny.port'=\{port\},shiny.host='\{host\}');library(\{appname\});\{appname\}::run_app()\\}}
+
+\item{...}{Other arguments to pass to \code{\link[renv:snapshot]{renv::snapshot()}}}
}
\value{
The \code{{dockerfiler}} object, invisibly.
}
\description{
-Build a container containing your Shiny App. \code{add_dockerfile()} creates
-a generic Dockerfile, while \code{add_dockerfile_shinyproxy()} and
+Build a container containing your Shiny App. \code{add_dockerfile()} and
+\code{add_dockerfile_with_renv()} and \code{add_dockerfile_with_renv()} creates
+a generic Dockerfile, while \code{add_dockerfile_shinyproxy()},
+\code{add_dockerfile_with_renv_shinyproxy()} , \code{add_dockerfile_with_renv_shinyproxy()} and
\code{add_dockerfile_heroku()} creates platform specific Dockerfile.
}
\examples{
\donttest{
# Add a standard Dockerfile
-if (interactive()) {
+if (interactive() & requireNamespace("dockerfiler")) {
add_dockerfile()
}
+# Crete a 'deploy' folder containing everything needed to deploy
+# the golem using docker based on {renv}
+if (interactive() & requireNamespace("dockerfiler")) {
+ add_dockerfile_with_renv(
+ # lockfile = "renv.lock", # uncomment to use existing renv.lock file
+ output_dir = "deploy"
+ )
+}
# Add a Dockerfile for ShinyProxy
-if (interactive()) {
+if (interactive() & requireNamespace("dockerfiler")) {
add_dockerfile_shinyproxy()
}
+
+# Crete a 'deploy' folder containing everything needed to deploy
+# the golem with ShinyProxy using docker based on {renv}
+if (interactive() & requireNamespace("dockerfiler")) {
+ add_dockerfile_with_renv(
+ # lockfile = "renv.lock",# uncomment to use existing renv.lock file
+ output_dir = "deploy"
+ )
+}
+
# Add a Dockerfile for Heroku
-if (interactive()) {
+if (interactive() & requireNamespace("dockerfiler")) {
add_dockerfile_heroku()
}
}
diff --git a/man/document_and_reload.Rd b/man/document_and_reload.Rd
index 8d0c84ec..95b60561 100644
--- a/man/document_and_reload.Rd
+++ b/man/document_and_reload.Rd
@@ -24,7 +24,7 @@ which defaults to \code{c("collate", "namespace", "rd")}.}
\item{load_code}{A function used to load all the R code in the package
directory. The default, \code{NULL}, uses the strategy defined by
-the \code{load} roxygen option, which defaults to \code{\link[roxygen2:load]{load_pkgload()}}.
+the \code{load} roxygen option, which defaults to \code{\link[roxygen2:load_pkgload]{load_pkgload()}}.
See \link[roxygen2]{load} for more details.}
\item{clean}{If \code{TRUE}, roxygen will delete all files previously
diff --git a/man/figures/logo.png b/man/figures/logo.png
deleted file mode 100644
index a149d478..00000000
Binary files a/man/figures/logo.png and /dev/null differ
diff --git a/man/fill_desc.Rd b/man/fill_desc.Rd
index 87c4885a..a851ae08 100644
--- a/man/fill_desc.Rd
+++ b/man/fill_desc.Rd
@@ -13,6 +13,7 @@ fill_desc(
author_email,
author_orcid = NULL,
repo_url = NULL,
+ pkg_version = "0.0.0.9000",
pkg = get_golem_wd()
)
}
@@ -33,6 +34,8 @@ fill_desc(
\item{repo_url}{URL (if needed)}
+\item{pkg_version}{The version of the package. Default is 0.0.0.9000}
+
\item{pkg}{Path to look for the DESCRIPTION. Default is \code{get_golem_wd()}.}
}
\value{
diff --git a/man/get_current_config.Rd b/man/get_current_config.Rd
new file mode 100644
index 00000000..b795d92b
--- /dev/null
+++ b/man/get_current_config.Rd
@@ -0,0 +1,16 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/config.R
+\name{get_current_config}
+\alias{get_current_config}
+\title{Get the path to the current config File}
+\usage{
+get_current_config(path = getwd())
+}
+\arguments{
+\item{path}{Path to start looking for the config}
+}
+\description{
+This function tries to guess where the golem-config file is located.
+If it can't find it, this function asks the
+user if they want to set the golem skeleton.
+}
diff --git a/man/get_golem_options.Rd b/man/get_golem_options.Rd
index b768d479..6f8a2a6c 100644
--- a/man/get_golem_options.Rd
+++ b/man/get_golem_options.Rd
@@ -18,38 +18,50 @@ server and UI from your app, in order to call the
parameters passed to \code{run_app()}.
}
\examples{
-\dontrun{
# Define and use golem_options
+if (interactive()) {
+ # 1. Pass parameters directly to `run_app`
-# 1. Pass parameters to `run_app`
-
-# to set default value, edit run_app like this :
-run_app <- function(
- title = "this",
- content = "that"
-) {
- with_golem_options(
- app = shinyApp(
- ui = app_ui,
- server = app_server
- ),
- golem_opts = list(
- p1 = p1,
- p3 = p3
- )
+ run_app(
+ title = "My Golem App",
+ content = "something"
)
-}
-# 2. Get the values from the UI side
+ # 2. Get the values
+ # 2.1 from the UI side
+
+ h1(get_golem_options("title"))
-h1(get_golem_options("title"))
+ # 2.2 from the server-side
-# 3. Get the value from the server-side
+ output$param <- renderPrint({
+ paste("param content = ", get_golem_options("content"))
+ })
-output$param <- renderPrint({
- paste("param p2 = ", get_golem_options("p2"))
-})
+ output$param_full <- renderPrint({
+ get_golem_options() # list of all golem options as a list.
+ })
+
+ # 3. If needed, to set default value, edit `run_app` like this :
+
+ run_app <- function(
+ title = "this",
+ content = "that",
+ ...
+ ) {
+ with_golem_options(
+ app = shinyApp(
+ ui = app_ui,
+ server = app_server
+ ),
+ golem_opts = list(
+ title = title,
+ content = content,
+ ...
+ )
+ )
+ }
}
}
diff --git a/man/golem_opts.Rd b/man/golem_opts.Rd
index fa7de33a..131887a4 100644
--- a/man/golem_opts.Rd
+++ b/man/golem_opts.Rd
@@ -1,75 +1,86 @@
% Generated by roxygen2: do not edit by hand
-% Please edit documentation in R/options.R
-\name{set_golem_options}
-\alias{set_golem_options}
-\alias{set_golem_wd}
-\alias{set_golem_name}
-\alias{set_golem_version}
+% Please edit documentation in R/golem-yaml-get.R, R/golem-yaml-set.R,
+% R/set_golem_options.R
+\name{get_golem_wd}
\alias{get_golem_wd}
\alias{get_golem_name}
\alias{get_golem_version}
+\alias{set_golem_wd}
+\alias{set_golem_name}
+\alias{set_golem_version}
+\alias{set_golem_options}
\title{\code{{golem}} options}
\usage{
-set_golem_options(
- golem_name = golem::pkg_name(),
- golem_version = golem::pkg_version(),
+get_golem_wd(use_parent = TRUE, pkg = golem::pkg_path())
+
+get_golem_name(
+ config = Sys.getenv("GOLEM_CONFIG_ACTIVE", Sys.getenv("R_CONFIG_ACTIVE", "default")),
+ use_parent = TRUE,
+ pkg = golem::pkg_path()
+)
+
+get_golem_version(
+ config = Sys.getenv("GOLEM_CONFIG_ACTIVE", Sys.getenv("R_CONFIG_ACTIVE", "default")),
+ use_parent = TRUE,
+ pkg = golem::pkg_path()
+)
+
+set_golem_wd(
golem_wd = golem::pkg_path(),
- app_prod = FALSE,
+ pkg = golem::pkg_path(),
talkative = TRUE
)
-set_golem_wd(path = golem::pkg_path(), talkative = TRUE)
-
set_golem_name(
name = golem::pkg_name(),
- path = golem::pkg_path(),
- talkative = TRUE
+ pkg = golem::pkg_path(),
+ talkative = TRUE,
+ old_name = golem::pkg_name()
)
set_golem_version(
version = golem::pkg_version(),
- path = golem::pkg_path(),
+ pkg = golem::pkg_path(),
talkative = TRUE
)
-get_golem_wd(use_parent = TRUE, path = golem::pkg_path())
-
-get_golem_name(
- config = Sys.getenv("R_CONFIG_ACTIVE", "default"),
- use_parent = TRUE,
- path = golem::pkg_path()
-)
-
-get_golem_version(
- config = Sys.getenv("R_CONFIG_ACTIVE", "default"),
- use_parent = TRUE,
- path = golem::pkg_path()
+set_golem_options(
+ golem_name = golem::pkg_name(),
+ golem_version = golem::pkg_version(),
+ golem_wd = golem::pkg_path(),
+ app_prod = FALSE,
+ talkative = TRUE,
+ config_file = golem::get_current_config(golem_wd)
)
}
\arguments{
-\item{golem_name}{Name of the current golem.}
+\item{use_parent}{\code{TRUE} to scan parent directories for
+configuration files if the specified config file isn't found.}
-\item{golem_version}{Version of the current golem.}
+\item{pkg}{The path to set the golem working directory.
+Note that it will be passed to \code{normalizePath}.}
-\item{golem_wd}{Working directory of the current golem package.}
+\item{config}{Name of configuration to read from. Defaults to
+the value of the \code{R_CONFIG_ACTIVE} environment variable
+("default" if the variable does not exist).}
-\item{app_prod}{Is the \code{{golem}} in prod mode?}
+\item{golem_wd}{Working directory of the current golem package.}
\item{talkative}{Should the messages be printed to the console?}
-\item{path}{The path to set the golem working directory.
-Note that it will be passed to \code{normalizePath}.}
-
\item{name}{The name of the app}
+\item{old_name}{The old name of the app, used when changing the name}
+
\item{version}{The version of the app}
-\item{use_parent}{\code{TRUE} to scan parent directories for
-configuration files if the specified config file isn't found.}
+\item{golem_name}{Name of the current golem.}
-\item{config}{Name of configuration to read from. Defaults to
-the value of the \code{R_CONFIG_ACTIVE} environment variable
-("default" if the variable does not exist).}
+\item{golem_version}{Version of the current golem.}
+
+\item{app_prod}{Is the \code{{golem}} in prod mode?}
+
+\item{config_file}{path to the {golem} config file}
}
\value{
Used for side-effects for the setters, and values from the
@@ -84,7 +95,7 @@ inside the \code{inst} folder.
\itemize{
\item \code{set_golem_options()} sets all the options, with the defaults from the functions below.
-\item \code{set_golem_wd()} defaults to \code{here::here()}, which is the package root when starting a golem.
+\item \code{set_golem_wd()} defaults to \code{golem::golem_wd()}, which is the package root when starting a golem.
\item \code{set_golem_name()} defaults \code{golem::pkg_name()}
\item \code{set_golem_version()} defaults \code{golem::pkg_version()}
}
diff --git a/man/install_dev_deps.Rd b/man/install_dev_deps.Rd
new file mode 100644
index 00000000..22f7fce8
--- /dev/null
+++ b/man/install_dev_deps.Rd
@@ -0,0 +1,44 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/install_dev_deps.R
+\name{install_dev_deps}
+\alias{install_dev_deps}
+\title{Install {golem} dev dependencies}
+\usage{
+install_dev_deps(force_install = FALSE, ...)
+}
+\arguments{
+\item{force_install}{If force_install is installed,
+then the user is not interactively asked
+to install them.}
+
+\item{...}{further arguments passed to the install function.}
+}
+\value{
+Used for side-effects
+}
+\description{
+This function will run rlang::check_installed() on:
+\itemize{
+\item {usethis}
+\item {pkgload}
+\item {dockerfiler}
+\item {devtools}
+\item {roxygen2}
+\item {attachment}
+\item {rstudioapi}
+\item {here}
+\item {fs}
+\item {desc}
+\item {pkgbuild}
+\item {processx}
+\item {rsconnect}
+\item {testthat}
+\item {rstudioapi}
+}
+}
+\examples{
+if (interactive()) {
+ install_dev_deps()
+}
+
+}
diff --git a/man/is_golem.Rd b/man/is_golem.Rd
new file mode 100644
index 00000000..784130f9
--- /dev/null
+++ b/man/is_golem.Rd
@@ -0,0 +1,18 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/is_golem.R
+\name{is_golem}
+\alias{is_golem}
+\title{Is the directory a golem-based app?}
+\usage{
+is_golem(path = getwd())
+}
+\arguments{
+\item{path}{Path to the directory to check.
+Defaults to the current working directory.}
+}
+\description{
+Trying to guess if \code{path} is a golem-based app.
+}
+\examples{
+is_golem()
+}
diff --git a/man/is_running.Rd b/man/is_running.Rd
index b7605526..adb6cee7 100644
--- a/man/is_running.Rd
+++ b/man/is_running.Rd
@@ -9,8 +9,6 @@ is_running()
\value{
TRUE if the running app is a \code{{golem}} based app,
FALSE otherwise.
-
-A boolean.
}
\description{
Note that this will return \code{TRUE} only if the application
diff --git a/man/maintenance_page.Rd b/man/maintenance_page.Rd
new file mode 100644
index 00000000..42bb5c7f
--- /dev/null
+++ b/man/maintenance_page.Rd
@@ -0,0 +1,17 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/with_opt.R
+\name{maintenance_page}
+\alias{maintenance_page}
+\title{maintenance_page}
+\usage{
+maintenance_page()
+}
+\value{
+an html_document
+}
+\description{
+A default html page for maintenance mode
+}
+\details{
+see the vignette \code{vignette("f_extending_golem", package = "golem")} for details.
+}
diff --git a/man/pkg_tools.Rd b/man/pkg_tools.Rd
index 14f802ab..d9a5869a 100644
--- a/man/pkg_tools.Rd
+++ b/man/pkg_tools.Rd
@@ -10,13 +10,13 @@ pkg_name(path = ".")
pkg_version(path = ".")
-pkg_path(path = ".", depth = 3)
+pkg_path()
}
\arguments{
\item{path}{Path to use to read the DESCRIPTION}
-
-\item{depth}{Number of parent directory to visit before
-deciding we are not in a package.}
+}
+\value{
+The value of the entry in the DESCRIPTION file
}
\description{
These are functions to help you navigate
diff --git a/man/prod.Rd b/man/prod.Rd
index bdabc03a..9255c15b 100644
--- a/man/prod.Rd
+++ b/man/prod.Rd
@@ -11,8 +11,6 @@ app_dev()
}
\value{
\code{TRUE} or \code{FALSE} depending on the status of \code{getOption( "golem.app.prod")}
-
-A boolean.
}
\description{
Is the app in dev mode or prod mode?
diff --git a/man/run_dev.Rd b/man/run_dev.Rd
index 3f12448a..eb25135a 100644
--- a/man/run_dev.Rd
+++ b/man/run_dev.Rd
@@ -4,12 +4,14 @@
\alias{run_dev}
\title{Run run_dev.R}
\usage{
-run_dev(file = "dev/run_dev.R", pkg = get_golem_wd())
+run_dev(file = "dev/run_dev.R", pkg = get_golem_wd(), save_all = TRUE)
}
\arguments{
\item{file}{File path to \code{run_dev.R}. Defaults to \code{R/run_dev.R}.}
\item{pkg}{Path to the root of the package. Default is \code{get_golem_wd()}.}
+
+\item{save_all}{boolean. If TRUE, save all open file before sourcing \code{file}}
}
\value{
Used for side-effect
diff --git a/man/testhelpers.Rd b/man/testhelpers.Rd
index 6ad0ed56..0b516339 100644
--- a/man/testhelpers.Rd
+++ b/man/testhelpers.Rd
@@ -35,7 +35,3 @@ A testthat result.
These functions are designed to be used inside the tests
in your Shiny app package.
}
-\examples{
-expect_shinytag(shiny::tags$span("1"))
-expect_shinytaglist(shiny::tagList(1))
-}
diff --git a/man/use_readme_rmd.Rd b/man/use_readme_rmd.Rd
new file mode 100644
index 00000000..89a04779
--- /dev/null
+++ b/man/use_readme_rmd.Rd
@@ -0,0 +1,30 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/use_readme.R
+\name{use_readme_rmd}
+\alias{use_readme_rmd}
+\title{Generate a README.Rmd}
+\usage{
+use_readme_rmd(
+ open = rlang::is_interactive(),
+ pkg_name = golem::get_golem_name(),
+ overwrite = FALSE,
+ pkg = golem::get_golem_wd()
+)
+}
+\arguments{
+\item{open}{Open the newly created file for editing? Happens in RStudio, if
+applicable, or via \code{\link[utils:file.edit]{utils::file.edit()}} otherwise.}
+
+\item{pkg_name}{The name of the package}
+
+\item{overwrite}{an optional \code{logical} flag; if \code{TRUE}, overwrite
+existing \code{README.Rmd}, else throws an error if \code{README.Rmd} exists}
+
+\item{pkg}{Path to the root of the package. Default is \code{get_golem_wd()}.}
+}
+\value{
+pure side-effect function that generates template \code{README.Rmd}
+}
+\description{
+Generate a README.Rmd
+}
diff --git a/man/with_golem_options.Rd b/man/with_golem_options.Rd
index 21bb7303..ad35ab25 100644
--- a/man/with_golem_options.Rd
+++ b/man/with_golem_options.Rd
@@ -4,16 +4,23 @@
\alias{with_golem_options}
\title{Add Golem options to a Shiny App}
\usage{
-with_golem_options(app, golem_opts, print = FALSE)
+with_golem_options(
+ app,
+ golem_opts,
+ maintenance_page = golem::maintenance_page,
+ print = FALSE
+)
}
\arguments{
\item{app}{the app object.}
-\item{golem_opts}{A list of Options to be added to the app}
+\item{golem_opts}{A list of options to be added to the app}
+
+\item{maintenance_page}{an html_document or a shiny tag list. Default is golem template.}
\item{print}{Whether or not to print the app. Default is to \code{FALSE}, which
-should be what you need 99.99\% of the time In case you need to
-actively print the app object, you can set it to \code{TRUE}.}
+should be what you need 99.99\% of the time. In case you need to
+actively print() the app object, you can set it to \code{TRUE}.}
}
\value{
a shiny.appObj object
diff --git a/tests/testthat/DESCRIPTION b/tests/testthat/DESCRIPTION
index f2f99f57..d0637eec 100644
--- a/tests/testthat/DESCRIPTION
+++ b/tests/testthat/DESCRIPTION
@@ -1,13 +1,16 @@
Package: shinyexample
Title: newtitle
Version: 0.0.0.9000
-Authors@R: person('firstname', 'lastname', email = 'name@test.com', role = c('cre', 'aut'))
+Authors@R: c(
+ person("Colin", "Fay", , "contact@colinfay.me", role = c("cre", "aut"),
+ comment = c(ORCID = "0000-0001-7343-1846"))
+ )
Description: Newdescription.
License: What license is it under?
Encoding: UTF-8
LazyData: true
-Imports:
- shiny,
+Imports:
+ shiny,
golem
RoxygenNote: 6.1.0
URL: http://repo_url.com
diff --git a/tests/testthat/helper-config.R b/tests/testthat/helper-config.R
index d9af3ab9..81554197 100644
--- a/tests/testthat/helper-config.R
+++ b/tests/testthat/helper-config.R
@@ -3,6 +3,12 @@ library(golem)
library(withr)
old_usethis.quiet <- getOption("usethis.quiet")
options("usethis.quiet" = TRUE)
+# Small hack to prevent warning from rlang::lang() in tests
+# This should be managed in {attempt} later on
+x <- suppressWarnings({
+ rlang::lang(print)
+})
+
### Funs
remove_file <- function(path) {
if (file.exists(path)) unlink(path, force = TRUE)
@@ -56,13 +62,15 @@ fakename <- sprintf(
gsub("[ :-]", "", Sys.time())
)
+
+## random dir
+randir <- paste0(sample(safe_let(), 10, TRUE), collapse = "")
+
tpdir <- normalizePath(tempdir())
unlink(file.path(tpdir, fakename), recursive = TRUE)
create_golem(file.path(tpdir, fakename), open = FALSE)
pkg <- file.path(tpdir, fakename)
-## random dir
-randir <- paste0(sample(safe_let(), 10, TRUE), collapse = "")
fp <- file.path("inst/app", randir)
dir.create(file.path(pkg, fp), recursive = TRUE)
@@ -71,8 +79,32 @@ rand_name <- function() {
}
withr::with_dir(pkg, {
- set_golem_options()
+ # Some weird things with {here}
+ unloadNamespace("here")
+ if (!file.exists(".here")) {
+ here::set_here(path_to_golem)
+ }
+ if (requireNamespace("desc", quietly = TRUE)) {
+ set_golem_options()
+ }
usethis::proj_set(pkg)
- orig_test <- set_golem_wd(pkg)
+ orig_test <- set_golem_wd(
+ pkg = pkg
+ )
usethis::use_mit_license("Golem")
})
+
+
+create_deploy_folder <- function(){
+file.path(
+ tempdir(),
+ make.names(
+ paste0(
+ "deploy",
+ round(
+ runif(1, min = 0, max = 99999)
+ )
+ )
+ )
+ )
+}
diff --git a/tests/testthat/test-add_deploy_helpers.R b/tests/testthat/test-add_deploy_helpers.R
index 8aef7553..70d9e9e0 100644
--- a/tests/testthat/test-add_deploy_helpers.R
+++ b/tests/testthat/test-add_deploy_helpers.R
@@ -1,5 +1,8 @@
test_that("add_dockerfiles", {
- skip_if_not_installed("dockerfiler", "0.1.4")
+ skip_if_not_installed("renv")
+ skip_if_not_installed("dockerfiler", "0.2.0")
+ skip_if_not_installed("attachment", "0.2.5")
+
with_dir(pkg, {
for (fun in list(
add_dockerfile,
@@ -9,9 +12,15 @@ test_that("add_dockerfiles", {
burn_after_reading(
"Dockerfile",
{
- output <- testthat::capture_output(
- fun(pkg = pkg, sysreqs = FALSE, open = FALSE)
+ withr::with_options(
+ c("golem.quiet" = FALSE),
+ {
+ output <- testthat::capture_output(
+ fun(pkg = pkg, sysreqs = FALSE, open = FALSE)
+ )
+ }
)
+
expect_exists("Dockerfile")
test <- stringr::str_detect(
output,
@@ -34,27 +43,31 @@ test_that("add_dockerfiles repos variation", {
burn_after_reading(
c("Dockerfile1", "Dockerfile2"),
{
- output1 <- testthat::capture_output(
- fun(
- pkg = pkg,
- sysreqs = FALSE,
- open = FALSE,
- repos = "https://cran.rstudio.com/",
- output = "Dockerfile1"
- )
- )
- output2 <- testthat::capture_output(
- fun(
- pkg = pkg,
- sysreqs = FALSE,
- open = FALSE,
- repos = c("https://cran.rstudio.com/"),
- output = "Dockerfile2"
- )
+ withr::with_options(
+ c("golem.quiet" = FALSE),
+ {
+ output1 <- testthat::capture_output(
+ fun(
+ pkg = pkg,
+ sysreqs = FALSE,
+ open = FALSE,
+ repos = "https://cran.rstudio.com/",
+ output = "Dockerfile1"
+ )
+ )
+ output2 <- testthat::capture_output(
+ fun(
+ pkg = pkg,
+ sysreqs = FALSE,
+ open = FALSE,
+ repos = c("https://cran.rstudio.com/"),
+ output = "Dockerfile2"
+ )
+ )
+ expect_exists("Dockerfile1")
+ expect_exists("Dockerfile2")
+ }
)
- expect_exists("Dockerfile1")
- expect_exists("Dockerfile2")
-
test1 <- stringr::str_detect(
output1,
@@ -76,60 +89,8 @@ test_that("add_dockerfiles repos variation", {
}
})
})
-test_that("add_dockerfiles multi repos", {
- skip_if_not_installed("dockerfiler", "0.1.4")
-
- repos <- c(
- bioc1 = "https://bioconductor.org/packages/3.10/data/annotation",
- bioc2 = "https://bioconductor.org/packages/3.10/data/experiment",
- CRAN = "https://cran.rstudio.com"
- )
- with_dir(pkg, {
- for (fun in list(
- add_dockerfile,
- add_dockerfile_heroku,
- add_dockerfile_shinyproxy
- )) {
- burn_after_reading(
- "Dockerfile",
- {
- output <- testthat::capture_output(
- fun(
- pkg = pkg,
- sysreqs = FALSE,
- open = FALSE,
- repos = repos,
- output = "Dockerfile"
- )
- )
-
- expect_exists("Dockerfile")
-
-
- test <- stringr::str_detect(
- output,
- "Dockerfile created at Dockerfile"
- )
- expect_true(test)
-
-
- to_find <- "RUN echo \"options(repos = c(bioc1 = 'https://bioconductor.org/packages/3.10/data/annotation', bioc2 = 'https://bioconductor.org/packages/3.10/data/experiment', CRAN = 'https://cran.rstudio.com'), download.file.method = 'libcurl', Ncpus = 4)\" >> /usr/local/lib/R/etc/Rprofile.site"
- # for R <= 3.4
- to_find_old <- "RUN echo \"options(repos = structure(c('https://bioconductor.org/packages/3.10/data/annotation', 'https://bioconductor.org/packages/3.10/data/experiment', 'https://cran.rstudio.com'), .Names = c('bioc1', 'bioc2', 'CRAN')), download.file.method = 'libcurl', Ncpus = 4)\" >> /usr/local/lib/R/etc/Rprofile.site"
-
- expect_true(
- sum(
- readLines(con = "Dockerfile") %in% c(to_find, to_find_old)
- ) == 1
- )
- }
- )
- }
- })
-})
-
test_that("add_rstudio_files", {
with_dir(pkg, {
for (fun in list(
@@ -140,11 +101,16 @@ test_that("add_rstudio_files", {
burn_after_reading(
"app.R",
{
- output <- testthat::capture_output(
- fun(
- pkg = pkg,
- open = FALSE
- )
+ withr::with_options(
+ c("golem.quiet" = FALSE),
+ {
+ output <- testthat::capture_output(
+ fun(
+ pkg = pkg,
+ open = FALSE
+ )
+ )
+ }
)
expect_exists("app.R")
test <- stringr::str_detect(
diff --git a/tests/testthat/test-add_files.R b/tests/testthat/test-add_files.R
index 456d3bee..ba8762e2 100644
--- a/tests/testthat/test-add_files.R
+++ b/tests/testthat/test-add_files.R
@@ -9,6 +9,12 @@ expect_add_file <- function(
name <- rand_name()
# Be sure to remove all files in case there are
remove_files("inst/app/www", ext)
+
+ # Checking that check_name_length is throwing an error
+ expect_error(
+ fun(c("a", "b")),
+ )
+
# Launch the function
fun(name, pkg = pak, open = FALSE)
if (fun_nms == "add_js_input_binding") {
@@ -108,6 +114,18 @@ test_that("add_files", {
pak = pkg,
fp = fp
)
+ expect_add_file(
+ add_html_template,
+ ext = "html",
+ pak = pkg,
+ fp = fp
+ )
+ expect_add_file(
+ add_partial_html_template,
+ ext = "html",
+ pak = pkg,
+ fp = fp
+ )
})
})
diff --git a/tests/testthat/test-add_modules.R b/tests/testthat/test-add_modules.R
index a1584aef..9a98bd29 100644
--- a/tests/testthat/test-add_modules.R
+++ b/tests/testthat/test-add_modules.R
@@ -15,7 +15,12 @@ test_that("add_module", {
lapply(tools::file_ext(script), function(x) testthat::expect_equal(x, "R"))
## Test message of function
remove_file("R/mod_output.R")
- output <- testthat::capture_output(add_module("output", open = FALSE))
+ withr::with_options(
+ c("golem.quiet" = FALSE),
+ {
+ output <- testthat::capture_output(add_module("output", open = FALSE))
+ }
+ )
expect_true(
stringr::str_detect(output, "File created at R/mod_output.R")
)
@@ -44,5 +49,20 @@ test_that("add_module", {
remove_file("R/mod_test2.R")
remove_file("R/mod_test2_fct_ftest.R")
remove_file("R/mod_test2_utils_utest.R")
+
+ # Checking that the mod_ prefix is removed and added
+ add_module(
+ "mod_mod_mod_test2.R",
+ open = FALSE,
+ pkg = pkg,
+ fct = "ftest",
+ utils = "utest"
+ )
+ expect_true(file.exists("R/mod_test2.R"))
+ expect_true(file.exists("R/mod_test2_fct_ftest.R"))
+ expect_true(file.exists("R/mod_test2_utils_utest.R"))
+ remove_file("R/mod_test2.R")
+ remove_file("R/mod_test2_fct_ftest.R")
+ remove_file("R/mod_test2_utils_utest.R")
})
})
diff --git a/tests/testthat/test-add_r_files.R b/tests/testthat/test-add_r_files.R
index 7cc95f25..8232bc54 100644
--- a/tests/testthat/test-add_r_files.R
+++ b/tests/testthat/test-add_r_files.R
@@ -9,6 +9,13 @@ test_that("add_fct and add_utils", {
add_fct("ui", pkg = pkg, open = FALSE, with_test = TRUE)
add_utils("ui", pkg = pkg, open = FALSE, with_test = TRUE)
+ expect_error(
+ add_fct(c("a", "b")),
+ )
+ expect_error(
+ add_utils(c("a", "b")),
+ )
+
expect_true(file.exists(util_file))
expect_true(file.exists(fct_file))
expect_true(file.exists("tests/testthat/test-utils_ui.R"))
@@ -21,6 +28,10 @@ test_that("add_fct and add_utils", {
expect_true(file.exists(sprintf("R/mod_%s_fct_ui.R", rand)))
expect_true(file.exists(sprintf("R/mod_%s_utils_ui.R", rand)))
+ expect_error(
+ add_module(c("a", "b")),
+ )
+
# If module not yet created an error is thrown
expect_error(
add_fct("ui", module = "notyetcreated", pkg = pkg, open = FALSE),
diff --git a/tests/testthat/test-config.R b/tests/testthat/test-config.R
index f5256e42..3f56c660 100644
--- a/tests/testthat/test-config.R
+++ b/tests/testthat/test-config.R
@@ -1,8 +1,24 @@
test_that("config works", {
with_dir(pkg, {
- expect_equal(get_golem_name(), fakename)
- expect_equal(get_golem_version(), "0.0.0.9000")
- expect_equal(normalizePath(get_golem_wd(), mustWork = FALSE), normalizePath(pkg, mustWork = FALSE))
+ # We'll try to be sure that
+ # golem_wd: !expr golem::pkg_path()
+ # is kept along the way
+ expect_equal(
+ tail(readLines("inst/golem-config.yml"), 1),
+ " golem_wd: !expr golem::pkg_path()"
+ )
+ expect_equal(
+ get_golem_name(),
+ fakename
+ )
+ expect_equal(
+ get_golem_version(),
+ "0.0.0.9000"
+ )
+ expect_equal(
+ normalizePath(get_golem_wd(), mustWork = FALSE),
+ normalizePath(pkg, mustWork = FALSE)
+ )
amend_golem_config(
key = "where",
value = "indev"
@@ -12,26 +28,53 @@ test_that("config works", {
value = "inprod",
config = "production"
)
-
- expect_equal(config::get("where", file = "inst/golem-config.yml"), "indev")
- expect_equal(config::get("where", config = "production", file = "inst/golem-config.yml"), "inprod")
+ expect_equal(
+ tail(readLines("inst/golem-config.yml"), 1),
+ " golem_wd: !expr golem::pkg_path()"
+ )
+ expect_equal(
+ config::get("where", file = "inst/golem-config.yml"),
+ "indev"
+ )
+ expect_equal(
+ config::get("where", config = "production", file = "inst/golem-config.yml"),
+ "inprod"
+ )
+
where_conf <- withr::with_envvar(
c("R_CONFIG_ACTIVE" = "production"),
{
config::get("where", file = "inst/golem-config.yml")
}
)
- expect_equal(where_conf, "inprod")
+ expect_equal(
+ where_conf,
+ "inprod"
+ )
set_golem_name("plop")
- expect_equal(get_golem_name(), "plop")
+ expect_equal(
+ get_golem_name(),
+ "plop"
+ )
set_golem_name(fakename)
set_golem_version("0.0.0.9001")
- expect_equal(get_golem_version(), "0.0.0.9001")
+ expect_equal(
+ get_golem_version(),
+ "0.0.0.9001"
+ )
set_golem_version("0.0.0.9000")
set_golem_wd(normalizePath("inst"))
- expect_equal(normalizePath(get_golem_wd()), normalizePath("inst"))
+ expect_equal(
+ normalizePath(get_golem_wd()),
+ normalizePath("inst")
+ )
set_golem_wd(pkg)
+ # Be sure that after setting the stuff the wd is still here::here()
+ expect_equal(
+ tail(readLines("inst/golem-config.yml"), 1),
+ " golem_wd: !expr golem::pkg_path()"
+ )
})
})
diff --git a/tests/testthat/test-create_golem.R b/tests/testthat/test-create_golem.R
index 0dd4a130..92992f06 100644
--- a/tests/testthat/test-create_golem.R
+++ b/tests/testthat/test-create_golem.R
@@ -2,7 +2,6 @@
### Helpers functions ----------------------------------------------------------
is_properly_populated_golem <- function(path) {
-
# All files excepts *.Rproj which changes based on the project name
expected_files <- c(
"DESCRIPTION",
@@ -62,7 +61,6 @@ dummy_dir <- tempfile(pattern = "dummy")
dir.create(dummy_dir)
withr::with_dir(dummy_dir, {
-
## Default
test_that("golem is created and properly populated", {
dummy_golem_path <- file.path(dummy_dir, "koko")
diff --git a/tests/testthat/test-desc.R b/tests/testthat/test-desc.R
index 7af2b91f..c1b7aa51 100644
--- a/tests/testthat/test-desc.R
+++ b/tests/testthat/test-desc.R
@@ -1,41 +1,80 @@
-
test_that("desc works", {
+ testthat::skip_if_not_installed("desc")
with_dir(pkg, {
- output <- capture_output(
- fill_desc(
- fakename,
- "newtitle",
- "Newdescription.",
- "firstname",
- "lastname",
- "name@test.com",
- "http://repo_url.com"
- )
+ withr::with_options(
+ c("golem.quiet" = FALSE),
+ {
+ output <- capture_output(
+ fill_desc(
+ pkg_name = fakename,
+ pkg_title = "newtitle",
+ pkg_description = "Newdescription.",
+ authors = person(
+ given = "firstname",
+ family = "lastname",
+ email = "name@test.com"
+ ),
+ repo_url = "http://repo_url.com",
+ pkg_version = "0.0.0.9000"
+ )
+ )
+ }
)
add_desc <- c(
fakename,
"newtitle",
"Newdescription.",
- "firstname",
- "lastname",
- "name@test.com",
- "http://repo_url.com"
+ "person('firstname', 'lastname', , 'name@test.com')",
+ "http://repo_url.com",
+ "0.0.0.9000"
)
desc <- readLines("DESCRIPTION")
expect_true(
all(
as.logical(lapply(
- add_desc,
+ add_desc[-4],
function(x) {
any(grepl(x, desc))
}
))
)
)
+ # add additional test, as authors = person(...) requires parsing test
+ tmp_test_add_desc <- eval(parse(text = add_desc[4]))
+ tmp_test_desc <- eval(parse(text = desc[[5]]))
+ expect_identical(
+ tmp_test_add_desc,
+ tmp_test_desc
+ )
expect_true(
stringr::str_detect(output, "DESCRIPTION file modified")
)
+
+ # test retrocompatibility
+ withr::with_options(
+ c("golem.quiet" = FALSE),
+ {
+ expect_warning(
+ fill_desc(
+ pkg_name = fakename,
+ pkg_title = "newtitle",
+ pkg_description = "Newdescription.",
+ author_first_name = "firstname",
+ author_last_name = "lastname",
+ author_email = "test@test.com"
+ )
+ )
+ expect_equal(
+ as.character(desc::desc_get("Title")),
+ "newtitle"
+ )
+ expect_equal(
+ as.character(desc::desc_get_authors()),
+ "firstname lastname "
+ )
+ }
+ )
})
})
diff --git a/tests/testthat/test-extra_sysreqs.R b/tests/testthat/test-extra_sysreqs.R
index 2b5f34d8..53b906cb 100644
--- a/tests/testthat/test-extra_sysreqs.R
+++ b/tests/testthat/test-extra_sysreqs.R
@@ -1,4 +1,9 @@
+skip_if_not_installed("dockerfiler", minimum_version = "0.2.0")
+
test_that("test extra sysreqs", {
+ skip_if_not_installed("renv")
+ skip_if_not_installed("dockerfiler", "0.2.0")
+ skip_if_not_installed("attachment", "0.2.5")
with_dir(pkg, {
for (fun in list(
add_dockerfile,
@@ -8,16 +13,20 @@ test_that("test extra sysreqs", {
burn_after_reading(
"Dockerfile",
{
- output <- testthat::capture_output(
- fun(
- pkg = pkg,
- sysreqs = FALSE,
- open = FALSE,
- extra_sysreqs = c("test1", "test2"),
- output = "Dockerfile"
- )
+ withr::with_options(
+ c("golem.quiet" = FALSE),
+ {
+ output <- testthat::capture_output(
+ fun(
+ pkg = pkg,
+ sysreqs = FALSE,
+ open = FALSE,
+ extra_sysreqs = c("test1", "test2"),
+ output = "Dockerfile"
+ )
+ )
+ }
)
-
expect_exists("Dockerfile")
test <- stringr::str_detect(
output,
diff --git a/tests/testthat/test-install_dev_deps.R b/tests/testthat/test-install_dev_deps.R
new file mode 100644
index 00000000..8eebb5fb
--- /dev/null
+++ b/tests/testthat/test-install_dev_deps.R
@@ -0,0 +1,32 @@
+test_that("install_dev_deps works", {
+ install_dev_deps(
+ force_install = TRUE,
+ repos = "https://cran.rstudio.com"
+ )
+ paks <- unique(
+ c(
+ "usethis",
+ "pkgload",
+ "dockerfiler",
+ "devtools",
+ "roxygen2",
+ "attachment",
+ "rstudioapi",
+ "here",
+ "fs",
+ "desc",
+ "pkgbuild",
+ "processx",
+ "rsconnect",
+ "testthat",
+ "rstudioapi"
+ )
+ )
+ for (
+ pak in paks
+ ) {
+ expect_true(
+ rlang::is_installed(pak)
+ )
+ }
+})
diff --git a/tests/testthat/test-is_golem.R b/tests/testthat/test-is_golem.R
new file mode 100644
index 00000000..8fe64dd0
--- /dev/null
+++ b/tests/testthat/test-is_golem.R
@@ -0,0 +1,8 @@
+test_that("is_golem works", {
+ expect_true(
+ is_golem(pkg)
+ )
+ expect_false(
+ is_golem(tempdir())
+ )
+})
diff --git a/tests/testthat/test-maintenance.R b/tests/testthat/test-maintenance.R
new file mode 100644
index 00000000..8464e04f
--- /dev/null
+++ b/tests/testthat/test-maintenance.R
@@ -0,0 +1,4 @@
+test_that("test maintenance_page", {
+ html <- maintenance_page()
+ expect_true(inherits(html, c("html_document", "shiny.tag.list", "list")))
+})
diff --git a/tests/testthat/test-make_dev.R b/tests/testthat/test-make_dev.R
index bbf46547..66013a26 100644
--- a/tests/testthat/test-make_dev.R
+++ b/tests/testthat/test-make_dev.R
@@ -60,7 +60,12 @@ test_that("test print_dev", {
test_that("test browser_button", {
- output <- capture_output_lines(browser_button())
+ withr::with_options(
+ c("golem.quiet" = FALSE),
+ {
+ output <- capture_output_lines(browser_button())
+ }
+ )
expect_true(
grepl('actionButton\\("browser", "browser"\\)', output[2])
)
diff --git a/tests/testthat/test-pkg_tools.R b/tests/testthat/test-pkg_tools.R
index d56c0a43..bc1af90a 100644
--- a/tests/testthat/test-pkg_tools.R
+++ b/tests/testthat/test-pkg_tools.R
@@ -1,9 +1,11 @@
+skip_if_not_installed("pkgload")
+
test_that("pkgtools works", {
withr::with_dir(pkg, {
- expect_equal(pkg_name(), fakename)
- expect_equal(pkg_version(), "0.0.0.9000")
+ expect_equal(pkgload::pkg_name(), fakename)
+ expect_equal(as.character(pkgload::pkg_version()), "0.0.0.9000")
# F-word windows path
skip_on_os("windows")
- expect_equal(pkg_path(), pkg)
+ expect_equal(pkgload::pkg_path(), pkg)
})
})
diff --git a/tests/testthat/test-renv_stuff.R b/tests/testthat/test-renv_stuff.R
new file mode 100644
index 00000000..6c226434
--- /dev/null
+++ b/tests/testthat/test-renv_stuff.R
@@ -0,0 +1,65 @@
+test_that("add_dockerfiles_renv and add_dockerfile_with_renv_shinyproxy all output file are present", {
+ skip_if_not_installed("renv")
+ skip_if_not_installed("dockerfiler", "0.2.0")
+ skip_if_not_installed("attachment", "0.2.5")
+ with_dir(pkg, {
+ for (fun in list(
+ add_dockerfile_with_renv,
+ add_dockerfile_with_renv_shinyproxy,
+ add_dockerfile_with_renv_heroku
+ )) {
+ deploy_folder <- create_deploy_folder()
+ desc::desc_set_authors(
+ person(
+ given = "colin",
+ family = "fay",
+ email = "contact@colinfay.me",
+ role = c("aut", "cre"),
+ comment = c(ORCID = "0000-0001-5879-4195")
+ )
+ )
+
+ fun(output_dir = deploy_folder, open = FALSE)
+
+ expect_exists(file.path(deploy_folder, "Dockerfile"))
+ expect_exists(file.path(deploy_folder, "Dockerfile_base"))
+ expect_exists(file.path(deploy_folder, "README"))
+ expect_exists(file.path(deploy_folder, "renv.lock.prod"))
+
+ expect_length(list.files(path = deploy_folder, pattern = "tar.gz$"), 1)
+ unlink(deploy_folder, force = TRUE, recursive = TRUE)
+ }
+ })
+})
+test_that("suggested package are not in renv prod", {
+ skip_if_not_installed("renv")
+ skip_if_not_installed("dockerfiler", "0.2.0")
+ skip_if_not_installed("attachment", "0.3.1")
+ with_dir(
+ pkg,
+ {
+ desc_file <- file.path("DESCRIPTION")
+ desc_lines <- readLines(desc_file)
+ # desc_lines <- c(desc_lines,"Suggests: \n idontexist")
+ desc_lines[desc_lines == "Suggests: "] <- "Suggests: \n idontexist,"
+ writeLines(desc_lines, desc_file)
+ deploy_folder <- create_deploy_folder()
+ desc::desc_set_authors(
+ person(
+ given = "colin",
+ family = "fay",
+ email = "contact@colinfay.me",
+ role = c("aut", "cre"),
+ comment = c(ORCID = "0000-0001-5879-4195")
+ )
+ )
+ add_dockerfile_with_renv(output_dir = deploy_folder, open = FALSE)
+
+ base <- paste(readLines(file.path(deploy_folder, "renv.lock.prod")), collapse = " ")
+ expect_false(grepl(pattern = "idontexist", x = base))
+ expect_true(grepl(pattern = "shiny", x = base))
+
+ unlink(deploy_folder, force = TRUE, recursive = TRUE)
+ }
+ )
+})
diff --git a/tests/testthat/test-test_helpers.R b/tests/testthat/test-test_helpers.R
index c1e4ccad..307e7e3d 100644
--- a/tests/testthat/test-test_helpers.R
+++ b/tests/testthat/test-test_helpers.R
@@ -1,13 +1,23 @@
test_that("test expect_shinytag", {
with_dir(pkg, {
- expect_equal(capture_output(expect_shinytag(favicon("jean"))), "")
- expect_error(expect_shinytag("pierre"))
+ withr::with_options(
+ c("golem.quiet" = FALSE),
+ {
+ expect_equal(capture_output(expect_shinytag(favicon("jean"))), "")
+ expect_error(expect_shinytag("pierre"))
+ }
+ )
})
})
test_that("test expect_shinytaglist", {
with_dir(pkg, {
- expect_equal(capture_output(expect_shinytaglist(shiny::tagList())), "")
- expect_error(expect_shinytaglist("test"))
+ withr::with_options(
+ c("golem.quiet" = FALSE),
+ {
+ expect_equal(capture_output(expect_shinytaglist(shiny::tagList())), "")
+ expect_error(expect_shinytaglist("test"))
+ }
+ )
})
})
diff --git a/tests/testthat/test-use_readme.R b/tests/testthat/test-use_readme.R
new file mode 100644
index 00000000..33d9f7e0
--- /dev/null
+++ b/tests/testthat/test-use_readme.R
@@ -0,0 +1,40 @@
+test_that("generate_readme_tmpl works", { res <- generate_readme_tmpl("my_pkg")
+ expect_true(
+ grepl("my_pkg", paste(res, collapse = " "))
+ )
+ expect_true(
+ grepl("my_pkg::run_app()", paste(res, collapse = " "))
+ )
+ expect_true(
+ grepl("covr::package_coverage", paste(res, collapse = " "))
+ )
+ expect_true(
+ grepl("unloadNamespace", paste(res, collapse = " "))
+ )
+ expect_true(
+ grepl("devtools::check", paste(res, collapse = " "))
+ )
+})
+
+
+test_that("check_overwrite works", {
+ expect_error(
+ check_overwrite(FALSE, golem_sys("utils/empty_readme.Rmd")),
+ "README.Rmd already exists. Set `overwrite = TRUE` to overwrite."
+ )
+})
+
+test_that("use_readme_rmd works", {
+ expect_true(
+ use_readme_rmd(
+ open = FALSE,
+ overwrite = TRUE,
+ pkg = getwd(),
+ pkg_name = "rand_name"
+ )
+ )
+ expect_true(
+ file.exists("README.Rmd")
+ )
+ devtools:::build_readme()
+})
diff --git a/tests/testthat/test-use_recomended.R b/tests/testthat/test-use_recomended.R
index 738c7370..cb457b13 100644
--- a/tests/testthat/test-use_recomended.R
+++ b/tests/testthat/test-use_recomended.R
@@ -1,5 +1,6 @@
test_that("test use_recommended_deps", {
testthat::skip_on_cran()
+ testthat::skip_if_not_installed("desc")
with_dir(pkg, {
packages <- c("shiny", "DT", "attempt", "glue", "golem", "htmltools")
to_add <- c()
@@ -11,7 +12,7 @@ test_that("test use_recommended_deps", {
expect_warning(
use_recommended_deps(recommended = to_add)
)
- deps <- desc::desc_get_deps(file = "DESCRIPTION")
+ deps <- desc_get_deps(file = "DESCRIPTION")
expect_true(
all(to_add %in% deps$package)
)
diff --git a/tests/testthat/test-zreload.R b/tests/testthat/test-zreload.R
index b97b1f22..5f0abd54 100644
--- a/tests/testthat/test-zreload.R
+++ b/tests/testthat/test-zreload.R
@@ -20,9 +20,9 @@ test_that("test document_and_reload", {
})
})
-test_that("test detach_all_attached", {
- with_dir(pkg_reload, {
- test <- detach_all_attached()
- testthat::expect_true(test)
- })
-})
+# test_that("test detach_all_attached", {
+# with_dir(pkg_reload, {
+# test <- detach_all_attached()
+# testthat::expect_true(test)
+# })
+# })
diff --git a/tests/testthat/test-zzzzzzzzzz.R b/tests/testthat/test-zzzzzzzzzz.R
index 82aa1a70..53321f1a 100644
--- a/tests/testthat/test-zzzzzzzzzz.R
+++ b/tests/testthat/test-zzzzzzzzzz.R
@@ -1,11 +1,7 @@
# # For setting back old usethis settings
try({
- if (exists("orig_test")) {
- usethis::proj_set(orig_test)
- }
- if (exists("pkg")) {
- unlink(pkg, TRUE, TRUE)
- }
-
+ unlink("README.Rmd", TRUE, TRUE)
+ unlink("README.md", TRUE, TRUE)
+ unlink(pkg, TRUE, TRUE)
options("usethis.quiet" = old_usethis.quiet)
})
diff --git a/vignettes/a_start.Rmd b/vignettes/a_start.Rmd
index 002671ec..8535ab89 100644
--- a/vignettes/a_start.Rmd
+++ b/vignettes/a_start.Rmd
@@ -1,5 +1,5 @@
---
-title: "Getting Started with {golem}"
+title: "a_start"
author: "Colin Fay"
date: "`r Sys.Date()`"
output: rmarkdown::html_vignette
@@ -32,25 +32,25 @@ install.packages("golem")
```
-The development version of `{golem}` can be installed from GitHub using the `{remotes}` package:
+The development version of `{golem}` can be installed from GitHub using the `{remotes}` package:
```{r}
remotes::install_github("Thinkr-open/golem")
```
-## Getting started
+## Getting started
-Note before using `{golem}`:
+Note before using `{golem}`:
- A `{golem}` app is contained inside a package, so knowing how to build a package is highly recommended. On the plus side, everything you know about package development can be reused in `{golem}`.
-- A `{golem}` app works better if you are working with `shiny modules`, so knowing how modules work is recommended, but not mandatory.
+- A `{golem}` app works better if you are working with `shiny modules`, so knowing how modules work is recommended, but not mandatory.
-In the rest of the Vignettes, we'll assume you're working in RStudio.
+In the rest of the Vignettes, we'll assume you're working in RStudio.
### Create a package
-Once the package is installed, you can got to File > New Project... in RStudio, and choose "Package for Shiny App Using golem" input.
+Once the package is installed, you can got to File > New Project... in RStudio, and choose "Package for Shiny App Using golem" input.
```{r, echo=FALSE, out.width="80%", fig.align="center", eval=TRUE}
knitr::include_graphics("golemtemplate.png")
@@ -69,7 +69,7 @@ try(fs::dir_delete(x), silent = TRUE)
golem::create_golem(path = x, package_name = "golex", open = FALSE)
```
-This command allows you to create "illegally-named" package (for example, `1234`) by passing the `check_name` argument to `FALSE`. Note that this is not recommended and __should only be done if you know what you are doing__.
+This command allows you to create "illegally-named" package (for example, `1234`) by passing the `check_name` argument to `FALSE`. Note that this is not recommended and __should only be done if you know what you are doing__.
Once you've got that, a new RStudio project will be launched. Here is the structure of this project:
@@ -77,7 +77,8 @@ Once you've got that, a new RStudio project will be launched. Here is the struct
z <- capture.output(fs::dir_tree(x))
z <- z[-1]
w <- lapply(
- z, function(x) {
+ z,
+ function(x) {
cat(x, "\n")
}
)
@@ -90,19 +91,19 @@ If you're already familiar with R packages, most of these files will seem very f
+ `R/app_config.R`: Used to read inside `{golem}` config file located at `inst/golem-config.yml`.
-+ `R/app_server.R`, `R/app_ui.R`: Top level UI and server elements.
++ `R/app_server.R`, `R/app_ui.R`: Top level UI and server elements.
+ `R/run_app.R`: a function to configure and launch the application.
+ `dev/`: Scripts that will be used along the process of developing your app. You don't need to fill all the script before starting: use them as a notebook for keeping track of what you're doing all along the project life.
-+ `inst/app/www`: Where you will add external dependencies in `www` (images, css, etc), notably added with the `golem` functions used to create external resources.
++ `inst/app/www`: Where you will add external dependencies in `www` (images, css, etc), notably added with the `golem` functions used to create external resources.
-+ `man`: Package documentation, to be generated by R & `{roxygen2}`.
++ `man`: Package documentation, to be generated by R & `{roxygen2}`.
## `dev/01_start.R`
-Once you've created your project, the first file that opens is `dev/01_start.R`. This file contains a series of commands that you'll have to run once, at the beginning of the project.
+Once you've created your project, the first file that opens is `dev/01_start.R`. This file contains a series of commands that you'll have to run once, at the beginning of the project.
Note that you don't have to fill everything, event thought it's strongly recommended.
@@ -112,13 +113,16 @@ First, fill the DESCRIPTION by adding information about the package that will co
```{r }
golem::fill_desc(
- pkg_name = "shinyexample", # The Name of the package containing the App
- pkg_title = "PKG_TITLE", # The Title of the package containing the App
- pkg_description = "PKG_DESC.", # The Description of the package containing the App
- author_first_name = "AUTHOR_FIRST", # Your First Name
- author_last_name = "AUTHOR_LAST", # Your Last Name
- author_email = "AUTHOR@MAIL.COM", # Your Email
- repo_url = NULL # The (optional) URL of the GitHub Repo
+ pkg_name = "shinyexample", # The name of the golem package containing the app (typically lowercase, no underscore or periods)
+ pkg_title = "PKG_TITLE", # What the Package Does (One Line, Title Case, No Period)
+ pkg_description = "PKG_DESC.", # What the package does (one paragraph).
+ authors = person(
+ given = "AUTHOR_FIRST", # Your First Name
+ family = "AUTHOR_LAST", # Your Last Name
+ email = "AUTHOR@MAIL.COM" # Your email
+ ),
+ repo_url = NULL, # The URL of the GitHub repo (optional),
+ pkg_version = "0.0.0.9000" # The version of the package containing the app
)
```
@@ -132,7 +136,7 @@ Please DO run this line of code, as it sets a series of global options inside `g
golem::set_golem_options()
```
-### Set common Files
+### Set common Files
If you want to use the MIT license, README, code of conduct, lifecycle badge, a news file, etc.
@@ -155,7 +159,7 @@ Create a template for tests:
golem::use_recommended_tests()
```
-About [tests in a package](https://r-pkgs.org/tests.html).
+About [tests in a package](https://r-pkgs.org/testing-basics.html).
### Use Recommended Packages
@@ -176,7 +180,7 @@ golem::remove_favicon()
golem::use_favicon(path = "path/to/favicon")
```
-Note that you can add an url, and the favicon will be downloaded to the `inst/app/www` folder.
+Note that you can add an url, and the favicon will be downloaded to the `inst/app/www` folder.
> **Note**: If you are deploying your app with [ShinyProxy](https://www.shinyproxy.io/), your favicon should have the `.png` extension, otherwise it is not going to work.
@@ -193,7 +197,7 @@ golem::use_utils_server()
## Try the app
-To run the app, launch :
+To run the app, launch :
```{r}
golem::run_dev()
diff --git a/vignettes/b_dev.Rmd b/vignettes/b_dev.Rmd
index aaa3dd82..367484af 100644
--- a/vignettes/b_dev.Rmd
+++ b/vignettes/b_dev.Rmd
@@ -1,5 +1,5 @@
---
-title: "Day to Day Dev with {golem}"
+title: "b_dev"
author: "Colin Fay"
date: "`r Sys.Date()`"
output: rmarkdown::html_vignette
@@ -45,7 +45,7 @@ Note that the `{attachment}` package should be installed on your machine.
attachment::att_amend_desc()
```
-About [package dependencies](https://r-pkgs.org/namespace.html).
+About [package dependencies](https://r-pkgs.org/dependencies-mindset-background.html).
### Add modules
@@ -139,7 +139,7 @@ Add more tests to your application:
usethis::use_test("app")
```
-About [testing a package](https://r-pkgs.org/tests.html).
+About [testing a package](https://r-pkgs.org/testing-basics.html).
## Documentation
diff --git a/vignettes/c_deploy.Rmd b/vignettes/c_deploy.Rmd
index 4021cd03..fd9b1cb0 100644
--- a/vignettes/c_deploy.Rmd
+++ b/vignettes/c_deploy.Rmd
@@ -1,5 +1,5 @@
---
-title: "Deploying Apps with {golem}"
+title: "c_deploy"
author: "Colin Fay"
date: "`r Sys.Date()`"
output: rmarkdown::html_vignette
@@ -18,7 +18,7 @@ $(document).ready(function () {
```{r setup, include = FALSE}
knitr::opts_chunk$set(
collapse = TRUE,
- comment = "#>",
+ comment = "#>",
eval = FALSE
)
```
@@ -28,18 +28,15 @@ knitr::opts_chunk$set(
When launching the app, you might have noticed that the `dev/run_dev.R` function calls `run_app()`, which has the following structure:
```{r}
-run_app <- function(
- ...
-) {
+run_app <- function(...) {
with_golem_options(
app = shinyApp(
- ui = app_ui,
+ ui = app_ui,
server = app_server
- ),
+ ),
golem_opts = list(...)
)
}
-
```
This function might looks a little bit weird, but there's a long story behind it, and you can read more about it [there](https://rtask.thinkr.fr/shinyapp-runapp-shinyappdir-difference/).
@@ -48,7 +45,7 @@ But long story short, this combination of `with_golem_options` & `golem_opts = l
```{r}
run_app(this = "that")
-# And in the app
+# And in the app
this <- get_golem_options("this")
```
@@ -69,6 +66,10 @@ golem::add_shinyserver_file()
### Docker
+#### without using {renv}
+
+
+
```{r}
# If you want to deploy via a generic Dockerfile
golem::add_dockerfile()
@@ -80,3 +81,83 @@ golem::add_dockerfile_shinyproxy()
golem::add_dockerfile_heroku()
```
+#### using {renv}
+
+
+#### CASE 1 : you didn't use renv during developpment process
+
+
+> this functions will create a "deploy" folder containing :
+
+```
+deploy/
++-- Dockerfile
++-- Dockerfile_base
++-- yourgolem_0.0.0.9000.tar.gz
++-- README
+\-- renv.lock.prod
+```
+
+then follow the README file
+
+
+```{r}
+# If you want to deploy via a generic Dockerfile
+golem::add_dockerfile_with_renv(output_dir = "deploy")
+
+# If you want to deploy to ShinyProxy
+golem::add_dockerfile_with_renv_shinyproxy(output_dir = "deploy")
+```
+
+If you would like to use {renv} during developpement, you can init a renv.lock file with
+
+```{r}
+attachment::create_renv_for_dev(dev_pkg = c(
+ "renv",
+ "devtools",
+ "roxygen2",
+ "usethis",
+ "pkgload",
+ "testthat",
+ "remotes",
+ "covr",
+ "attachment",
+ "pak",
+ "dockerfiler",
+ "golem"
+))
+```
+an activate {renv} with
+
+```{r}
+renv::activate()
+```
+
+
+
+
+
+#### CASE 2 : you already have a renv.lock file for your project
+
+
+```{r}
+
+# If you want to deploy via a generic Dockerfile
+golem::add_dockerfile_with_renv(output_dir = "deploy", lockfile = "renv.lock")
+
+# If you want to deploy to ShinyProxy
+golem::add_dockerfile_with_renv_shinyproxy(output_dir = "deploy", lockfile = "renv.lock")
+```
+
+> this functions will create a "deploy" folder containing :
+
+```
+deploy/
++-- Dockerfile
++-- Dockerfile_base
++-- yourgolem_0.0.0.9000.tar.gz
++-- README
+\-- renv.lock.prod
+```
+
+then follow the README file
diff --git a/vignettes/d_js.Rmd b/vignettes/d_js.Rmd
index 72629009..757b3a42 100644
--- a/vignettes/d_js.Rmd
+++ b/vignettes/d_js.Rmd
@@ -1,5 +1,5 @@
---
-title: "Using {golem} js functions"
+title: "d_js"
author: "Colin Fay"
date: "`r Sys.Date()`"
output: rmarkdown::html_vignette
diff --git a/vignettes/e_config.Rmd b/vignettes/e_config.Rmd
index 5339ec26..2ec72636 100644
--- a/vignettes/e_config.Rmd
+++ b/vignettes/e_config.Rmd
@@ -1,5 +1,5 @@
---
-title: "Using golem config"
+title: "e_config"
output: rmarkdown::html_vignette
vignette: >
%\VignetteIndexEntry{config}
@@ -19,7 +19,8 @@ x <- file.path(
)
unlink(x, TRUE, TRUE)
-create_golem(x, package_name = "golex", open = FALSE)
+x <- golem::create_golem(x, package_name = "golex", open = FALSE)
+old <- setwd(x)
knitr::opts_knit$set(root.dir = x)
```
@@ -27,6 +28,10 @@ knitr::opts_knit$set(root.dir = x)
library(golem)
```
+```{r echo = FALSE}
+old <- setwd(x)
+```
+
## About `inst/golem-config.yml`
When you start a new `{golem}` application, you'll find a file called `golem-config.yml` in the `inst/` folder.
@@ -39,13 +44,17 @@ This config file is based on the [`{config}`](https://github.com/rstudio/config)
Here is what the default config file looks like:
-```{r echo = FALSE, comment= ""}
-cat(
- sep = "\n",
- readLines(
- "inst/golem-config.yml"
- )
-)
+```
+default:
+ golem_name: golex
+ golem_version: 0.0.0.9000
+ app_prod: no
+
+production:
+ app_prod: yes
+
+dev:
+ golem_wd: !expr golem::pkg_path()
```
+ default/golem_name, default/golem_version, default/app_prod are usable across the whole life of your golem app: while developing, and also when in production.
@@ -60,6 +69,15 @@ These options are globally set with:
set_golem_options()
```
+```{r echo = FALSE, comment= "", }
+cat(
+ sep = "\n",
+ readLines(
+ "inst/golem-config.yml"
+ )
+)
+```
+
The functions reading the options in this config file are:
```{r}
@@ -76,6 +94,15 @@ set_golem_wd(".")
set_golem_version("0.0.1")
```
+```{r echo = FALSE, comment= "", }
+cat(
+ sep = "\n",
+ readLines(
+ "inst/golem-config.yml"
+ )
+)
+```
+
## Using `golem-config`
@@ -95,6 +122,7 @@ amend_golem_config(
)
```
+
Will result in a `golem-config.yml` file as such:
```{r echo = FALSE, comment= ""}
@@ -143,4 +171,8 @@ The idea is also that the `golem-config.yml` file is shareable across `{golem}`
## Note for `{golem}` < 0.2.0 users
-If you've built an app with `{golem}` before the version 0.2.0, this config file doesn't exist: you'll be prompted to create it if you update a newer version of `{golem}`.
\ No newline at end of file
+If you've built an app with `{golem}` before the version 0.2.0, this config file doesn't exist: you'll be prompted to create it if you update a newer version of `{golem}`.
+
+```{r echo = FALSE}
+setwd(old)
+```
diff --git a/vignettes/f_extending_golem.Rmd b/vignettes/f_extending_golem.Rmd
index d9f6b087..4fcae1c6 100644
--- a/vignettes/f_extending_golem.Rmd
+++ b/vignettes/f_extending_golem.Rmd
@@ -1,5 +1,5 @@
---
-title: "Extending {golem}"
+title: "f_extending_golem"
output: rmarkdown::html_vignette
vignette: >
%\VignetteIndexEntry{f_extending_golem}
@@ -10,23 +10,23 @@ vignette: >
```{r, include = FALSE}
knitr::opts_chunk$set(
collapse = TRUE,
- comment = "#>",
+ comment = "#>",
eval = FALSE
)
```
-This Vignette discusses how you can extend `{golem}`.
+This Vignette discusses how you can extend `{golem}`.
## Project Hooks
### What it is
-The `create_golem()` function comes with a `project_hook` parameter, a function run just after the `{golem}` project creation.
-It can be used to modify the project structure automatically just after its creation.
+The `create_golem()` function comes with a `project_hook` parameter, a function run just after the `{golem}` project creation.
+It can be used to modify the project structure automatically just after its creation.
This allows you to define custom behavior when creating `{golem}` based app, that can be used for:
-+ Adding a different front-end template in `R/app_ui.R`
++ Adding a different front-end template in `R/app_ui.R`
+ Changing configuration options in `inst/golem-config.yml`
@@ -36,24 +36,24 @@ This allows you to define custom behavior when creating `{golem}` based app, tha
+ etc.
-### How it works
+### How it works
-The function is called __after__ the default project has been created, and is executed __in the directory of the created package__.
+The function is called __after__ the default project has been created, and is executed __in the directory of the created package__.
Here is a rough step by step of what happens when a project is created with `{golem}`:
1. The package name is generated
-1. The directory that will receive the package is created
+1. The directory that will receive the package is created
1. Default `{golem}` template is copied and pasted
1. R moves to the directory of the newly created project, and runs the `project_hook` function
1. R moves back to the previous directory, and removes comments if needed
-1. Project is open
+1. Project is open
### Defining your own `project_hook`
-The best way to extend `{golem}` project hook functionality is by defining this `project_hook` function in an external package.
-This will allow this function to be used inside the `{golem}` creation RStudio project creation widget:
+The best way to extend `{golem}` project hook functionality is by defining this `project_hook` function in an external package.
+This will allow this function to be used inside the `{golem}` creation RStudio project creation widget:
-![](rstudioprojecthook.png)
+![](rstudioprojecthook.png)
> Note that inside this widget, the function should be explicitely namespaced (pkg::fun)
@@ -70,31 +70,29 @@ These parameters might not be used inside your own hook, but __they need to be s
Here is an example of a function that can be used to remove the `dev/` folder:
```{r}
-no_dev <- function(path, package_name, ...){
- fs::dir_delete("dev")
+no_dev <- function(path, package_name, ...) {
+ fs::dir_delete("dev")
}
create_golem("ici", project_hook = no_dev)
```
-This one will create a CSS:
+This one will create a CSS:
```{r}
-new_css <- function(path, package_name, ...){
-
+new_css <- function(path, package_name, ...) {
css_path <- fs::path_abs("inst/app/www/custom.css")
-
+
fs::file_create(css_path)
-
- write_there <- function(...){
+
+ write_there <- function(...) {
write(..., file = css_path, append = TRUE)
}
-
+
write_there("body {")
write_there(" background-color:red;")
write_there("}")
-
- cli::cat_bullet("CSS generated")
-
+
+ cli_cat_bullet("CSS generated")
}
create_golem("ici", project_hook = new_css)
@@ -105,12 +103,12 @@ create_golem("ici", project_hook = new_css)
### What it is
Module templates are a way to define your own content for creating the module script in `R/`.
-It allows to extend `{golem}` module template functionality by creating your own content inside the module file.
+It allows to extend `{golem}` module template functionality by creating your own content inside the module file.
-### How it works
+### How it works
-The function is called after the file(s) creation.
-Here is a step by step of what happens when the `add_module` function is called:
+The function is called after the file(s) creation.
+Here is a step by step of what happens when the `add_module` function is called:
1. Name is created, and so is the `R/` directory if needed.
1. The fct_ and utils_ files are created if necessary
@@ -123,9 +121,9 @@ Here is a step by step of what happens when the `add_module` function is called:
### Defining your own `module_template`
-You can then define your own function inside your `{golem}` based application, but chances are you will be defining them into your own package.
+You can then define your own function inside your `{golem}` based application, but chances are you will be defining them into your own package.
-Module template functions will receive, by default, the following parameters from `add_modules()`.
+Module template functions will receive, by default, the following parameters from `add_modules()`.
+ `name`: the name of the module
+ `path`: the path to the file in R/
@@ -137,16 +135,16 @@ These parameters might not be used inside your own function, but __they need to
### Example
```{r}
-my_tmpl <- function(name, path, export, ...){
- # Define a template that only write the name of the
- # module in the file
- write(name, path)
+my_tmpl <- function(name, path, export, ...) {
+ # Define a template that only write the name of the
+ # module in the file
+ write(name, path)
}
golem::add_module(name = "custom", module_template = my_tmpl)
-my_other_tmpl <- function(name, path, ...){
- # Copy and paste a file from somewhere else
- file.copy(..., path)
+my_other_tmpl <- function(name, path, ...) {
+ # Copy and paste a file from somewhere else
+ file.copy(..., path)
}
golem::add_module(name = "custom", module_template = my_other_tmpl)
```
@@ -159,10 +157,10 @@ golem::add_module(name = "custom", module_template = my_other_tmpl)
JavaScript, CSS and Sass template allow to use your own functions to add code when creating JavaScript files, JavaScript handlers and CSS or Sass files.
These templates work inside `add_js_file()`, `add_js_handler()`, `add_css_file()` and `add_sass_file()`.
-### How it works
+### How it works
-The function is called after the file creation.
-Here is a step by step of what happens when these functions are called:
+The function is called after the file creation.
+Here is a step by step of what happens when these functions are called:
1. Name is created
1. The path is generated
@@ -174,11 +172,11 @@ Here is a step by step of what happens when these functions are called:
### Defining your own `template`
-You can then define your own function inside your `{golem}` based application, but chances are you will be defining them into your own package.
+You can then define your own function inside your `{golem}` based application, but chances are you will be defining them into your own package.
-File template functions will receive, by default, the following parameters from the `add_*()` function.
+File template functions will receive, by default, the following parameters from the `add_*()` function.
-+ `path`: the path to the file
++ `path`: the path to the file
+ `...` further arguments
These parameters might not be used inside your own function, but __they need to be set in the function skeleton__, for compatibility reasons.
@@ -186,13 +184,13 @@ These parameters might not be used inside your own function, but __they need to
### Example
```{r}
-my_tmpl <- function(path, ...){
- # Define a template that only write the name of the
- # module in the file
- write_there <- function(...){
+my_tmpl <- function(path, ...) {
+ # Define a template that only write the name of the
+ # module in the file
+ write_there <- function(...) {
write(..., file = path, append = TRUE)
}
-
+
write_there("body {")
write_there(" background-color:red;")
write_there("}")
@@ -200,6 +198,107 @@ my_tmpl <- function(path, ...){
golem::add_css_file(name = "custom", template = my_tmpl)
```
+## Turn on the maintenance mode
+
+### What it is
+
+From time to time, you need your application to be unavailble: database update, API changes, etc.
+In order to keep your app running but make it unavailable, you can use a __maintenance mode__.
+When this maintenance mode is turned on, your application will be paused and a specific page will be displayed to your users.
+
+`{golem}` comes with a default maintenance page, and you can replace it with you own page.
+
+### How to set the maintenance mode
+The maintenance mode will be turned on whenever the R process detects that the `GOLEM_MAINTENANCE_ACTIVE` environment variable is set to TRUE.
+
+To visualize the maintenance page locally, you can run the following:
+
+```{r eval = FALSE}
+withr::with_envvar(
+ c("GOLEM_MAINTENANCE_ACTIVE" = TRUE),
+ {
+ golem::run_dev()
+ }
+)
+```
+
+
+or
+
+```{r eval = FALSE}
+Sys.setenv("GOLEM_MAINTENANCE_ACTIVE" = TRUE)
+golem::run_dev()
+```
+
+If you're deploying on Posit Connect, you can set this variable in the setup panel.
+
+If in command line, you can also do
+
+```
+export GOLEM_MAINTENANCE_ACTIVE=TRUE && Rscript -e "mygolem::run_app()"
+```
+
+
+### The maintenance page
+
+`{golem}` comes with a default maintenance page, but you can override it and use your own custom page.
+
+In order to use your own page, you need to pass either an `html_document` or a `tagList` to the `with_golem_options` function in `run_app.R`:
+
+```{r}
+run_app <- function(
+ onStart = NULL,
+ options = list(),
+ enableBookmarking = NULL,
+ uiPattern = "/",
+ ...) {
+ with_golem_options(
+ app = shinyApp(
+ ui = app_ui,
+ server = app_server,
+ onStart = onStart,
+ options = options,
+ enableBookmarking = enableBookmarking,
+ uiPattern = uiPattern
+ ),
+ golem_opts = list(...),
+ maintenance_page = tagList(
+ fluidRow(
+ h1("Under maintenance"),
+ span("Coming soon...")
+ )
+ )
+ )
+}
+```
+
+or:
+
+```{r}
+run_app <- function(
+ onStart = NULL,
+ options = list(),
+ enableBookmarking = NULL,
+ uiPattern = "/",
+ ...) {
+ with_golem_options(
+ app = shinyApp(
+ ui = app_ui,
+ server = app_server,
+ onStart = onStart,
+ options = options,
+ enableBookmarking = enableBookmarking,
+ uiPattern = uiPattern
+ ),
+ golem_opts = list(...),
+ maintenance_page = shiny::htmlTemplate(
+ filename = app_sys(
+ "custom_maintenance_page.html"
+ )
+ )
+ )
+}
+```
diff --git a/vignettes/z_golem_cheatsheet.Rmd b/vignettes/z_golem_cheatsheet.Rmd
index 4c1c9199..10c3967b 100644
--- a/vignettes/z_golem_cheatsheet.Rmd
+++ b/vignettes/z_golem_cheatsheet.Rmd
@@ -1,5 +1,5 @@
---
-title: "{golem} cheatsheet"
+title: "e_golem_cheatsheet"
output: rmarkdown::html_vignette
vignette: >
%\VignetteIndexEntry{e_golem_cheatsheet}