diff --git a/DESCRIPTION b/DESCRIPTION index 9937fdf..3a5953d 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,12 +1,13 @@ Type: Package Package: audit.workbench Title: RStudio/Workbench User Acceptance Tests -Version: 0.6.5 -Authors@R: +Version: 0.6.6 +Authors@R: person("Jumping", "Rivers", , "info@jumpingrivers.com", role = c("aut", "cre")) Description: Testing whether data scientists can do what they expect in Posit Workbench. License: file LICENSE +URL: https://jumpingrivers.github.io/audit.workbench/ Imports: audit.base (>= 0.6.20), BiocManager, @@ -28,15 +29,14 @@ Imports: yaml Suggests: reticulate, - rvest, rstudioapi, + rvest, testthat (>= 3.0.0) Remotes: jumpingrivers/audit.base, jumpingrivers/serverheaders Config/testthat/edition: 3 Encoding: UTF-8 -LazyData: false Language: en-GB -RoxygenNote: 7.3.2 -URL: https://jumpingrivers.github.io/audit.workbench/ +LazyData: false +RoxygenNote: 7.3.3 diff --git a/NAMESPACE b/NAMESPACE index 318e3fe..80df0b9 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -19,5 +19,4 @@ export(check_rmd_html) export(check_rmd_pdf) export(check_rmd_word) export(create_config) -importFrom(dplyr,"%>%") importFrom(rlang,.data) diff --git a/NEWS.md b/NEWS.md index cfa32e6..386877e 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,3 +1,7 @@ +# audit.workbench 0.6.6 *2026-01-22* +- fix: Parsing Posit versions #20 +- chore: Linting and air'ing + # audit.workbench 0.6.5 *2025-02-22* - feat: The {rstudioapi} package is now optional @@ -19,7 +23,7 @@ # audit.workbench 0.5.0 *2023-06-21* - feat: Use %>% instead of |> - feat: Add initial report -- feat: Standardise function names with +- feat: Standardise function names with # audit.workbench 0.4.0 *2023-06-11* - feat: Initial version diff --git a/R/audit_details.R b/R/audit_details.R index b0d8893..c35a26f 100644 --- a/R/audit_details.R +++ b/R/audit_details.R @@ -1,6 +1,8 @@ audit_details = function(server) { - list(user = Sys.info()[["user"]], - server = server, - time = Sys.time(), - version = utils::packageVersion("audit.workbench")) + list( + user = Sys.info()[["user"]], + server = server, + time = Sys.time(), + version = utils::packageVersion("audit.workbench") + ) } diff --git a/R/check.R b/R/check.R index 1619d7e..9f5082d 100644 --- a/R/check.R +++ b/R/check.R @@ -14,9 +14,7 @@ #' * 2: No clean-up and display build steps #' @importFrom rlang .data #' @export -check = function(server, - dir = ".", - debug_level = 0:2) { +check = function(server, dir = ".", debug_level = 0:2) { debug_level = audit.base::get_debug_level(force(debug_level)) check_list = list() @@ -28,12 +26,14 @@ check = function(server, check_list$sys_deps = check_sys_libs(debug_level) check_list$versions = check_versions(debug_level) cli::cli_h2("Starting checks") - r6_inits = audit.base::init_r6_checks(dir = dir, - file = "config-uat-psw.yml", - pkg_name = "audit.workbench") + r6_inits = audit.base::init_r6_checks( + dir = dir, + file = "config-uat-psw.yml", + pkg_name = "audit.workbench" + ) lapply(r6_inits, function(r6) r6$check(debug_level = debug_level)) - results = purrr::map_dfr(r6_inits, ~.x$get_log()) + results = purrr::map_dfr(r6_inits, ~ .x$get_log()) check_list$results = dplyr::arrange(results, .data$group, .data$short) cli::cli_h1("All checks complete") - return(invisible(check_list)) + invisible(check_list) } diff --git a/R/check_core_r_pkgs.R b/R/check_core_r_pkgs.R index 7d7b595..fca525e 100644 --- a/R/check_core_r_pkgs.R +++ b/R/check_core_r_pkgs.R @@ -11,7 +11,7 @@ check_core_r_pkgs = R6::R6Class( #' @param debug_level See check() for details check = function(debug_level) { private$checker(testing_core_r_pkgs(debug_level)) - return(invisible(NULL)) + invisible(NULL) } ), private = list( @@ -30,14 +30,16 @@ testing_core_r_pkgs = function(debug_level) { if (length(missing_r_pkgs) > 0L) { cli::cli_abort("Core R packages are missing: {missing_r_pkgs}") } - return(TRUE) + TRUE } get_core_r_packages = function() { if (requireNamespace("rstudioapi", quietly = TRUE)) { core = rstudioapi::getRStudioPackageDependencies()$name } else if (requireNamespace("rstudioapi", quietly = TRUE)) { - html = rvest::read_html("https://docs.posit.co/ide/server-pro/reference/r_package_dependencies.html") #nolint + html = rvest::read_html( + "https://docs.posit.co/ide/server-pro/reference/r_package_dependencies.html" + ) #nolint cells = rvest::html_nodes(html, "td") values = purrr::map_chr(cells, rvest::html_text2) all = tibble::tibble( @@ -49,5 +51,5 @@ get_core_r_packages = function() { } else { stop("Install either rstudioapi or rvest to check core packages ") } - return(sort(core)) + sort(core) } diff --git a/R/check_file_permissions.R b/R/check_file_permissions.R index 88069fe..6897e08 100644 --- a/R/check_file_permissions.R +++ b/R/check_file_permissions.R @@ -10,7 +10,7 @@ check_file_permissions = R6::R6Class( #' @param debug_level See check() for details check = function(debug_level) { private$checker(testing_file_permissions(debug_level)) - return(invisible(NULL)) + invisible(NULL) } ), private = list( @@ -31,7 +31,6 @@ testing_file_permissions = function(debug_level) { # Convert the string to an integer, so that we can use it to make comparisons: file_permissions = strtoi(permissions_on_file) stopifnot("File permissions incorrect" = file_permissions >= 600) - } - ) - return(invisible(TRUE)) + }) + invisible(TRUE) } diff --git a/R/check_git_cloning.R b/R/check_git_cloning.R index f1fedb8..cc48a7a 100644 --- a/R/check_git_cloning.R +++ b/R/check_git_cloning.R @@ -10,7 +10,7 @@ check_git_cloning = R6::R6Class( #' @param debug_level See `check()` for details check = function(debug_level) { private$checker(git_cloning(debug_level)) - return(invisible(NULL)) + invisible(NULL) } ), private = list( @@ -25,8 +25,11 @@ git_cloning = function(debug_level) { git_clone_url = "https://github.com/jumpingrivers/diffify.git" git_local_folder = file.path(tempdir(), "diffify") - system2("git", args = c("clone", "--depth", "1", git_clone_url, git_local_folder)) + system2( + "git", + args = c("clone", "--depth", "1", git_clone_url, git_local_folder) + ) withr::defer(unlink(git_local_folder, recursive = TRUE)) success = dir.exists(git_local_folder) - return(success) + success } diff --git a/R/check_package.R b/R/check_package.R index 0f74ccf..b2e20bc 100644 --- a/R/check_package.R +++ b/R/check_package.R @@ -14,7 +14,7 @@ check_cran = R6::R6Class( #' @param debug_level See check() for details check = function(debug_level) { private$checker(testing_cran(debug_level)) - return(invisible(NULL)) + rinvisible(NULL) } ), private = list( @@ -37,7 +37,7 @@ check_bioconductor = R6::R6Class( #' @param debug_level See check() for details check = function(debug_level) { private$checker(testing_bioconductor(debug_level)) - return(invisible(NULL)) + invisible(NULL) } ), private = list( @@ -60,7 +60,7 @@ check_github = R6::R6Class( #' @param debug_level See check() for details check = function(debug_level) { private$checker(testing_github(debug_level)) - return(invisible(NULL)) + invisible(NULL) } ), private = list( @@ -76,14 +76,17 @@ testing_cran = function(debug_level) { pkg_name = "drat" is_installed = install_packages(pkg_name, quiet = TRUE) stopifnot("pkg unable to be installed" = is_installed) - return(invisible(TRUE)) + invisible(TRUE) } testing_github = function(debug_level) { - installed_pkg = remotes::install_github("jumpingrivers/datasauRus", - quiet = TRUE, force = TRUE) + installed_pkg = remotes::install_github( + "jumpingrivers/datasauRus", + quiet = TRUE, + force = TRUE + ) stopifnot(installed_pkg == "datasauRus") - return(invisible(TRUE)) + invisible(TRUE) } testing_bioconductor = function(debug_level) { @@ -94,7 +97,7 @@ testing_bioconductor = function(debug_level) { lapply(repos, function(repo) { stopifnot("Unable to access bioconductor repo" = !httr::http_error(repo)) }) - return(invisible(TRUE)) + invisible(TRUE) } install_packages = function(pkgs, quiet = FALSE) { @@ -104,7 +107,10 @@ install_packages = function(pkgs, quiet = FALSE) { # install.packages() doesn't throw an error if the pkg install fails # instead we capture the warning using capture() - that then changes the value of `e` # Hence: if e isn't null, something bad has happened. - withCallingHandlers(utils::install.packages(pkgs, quiet = quiet), warning = capture) + withCallingHandlers( + utils::install.packages(pkgs, quiet = quiet), + warning = capture + ) # If pkg not installed, return FALSE is.null(e) } diff --git a/R/check_posit_drivers.R b/R/check_posit_drivers.R index 35c8301..b202485 100644 --- a/R/check_posit_drivers.R +++ b/R/check_posit_drivers.R @@ -8,9 +8,10 @@ check_posit_drivers = function(debug_level) { software = "Posit pro-drivers", installed_version = installed_version, upgrade = upgrade, - version = latest_version) + version = latest_version + ) audit.base::print_colour_versions(installed) - return(installed) + installed } get_installed_posit_driver = function() { @@ -18,11 +19,15 @@ get_installed_posit_driver = function() { if (file.exists(fname)) { odbc = readLines(fname, warn = FALSE) versions = odbc[stringr::str_starts(odbc, "#", negate = TRUE)] - versions = stringr::str_extract(versions, "RStudioVersion = (.*)", group = TRUE) + versions = stringr::str_extract( + versions, + "RStudioVersion = (.*)", + group = TRUE + ) versions = versions[!is.na(versions)] installed_version = unique(versions) } else { installed_version = NA_character_ } - return(installed_version) + installed_version } diff --git a/R/check_posit_version.R b/R/check_posit_version.R index fc3345b..4e674a2 100644 --- a/R/check_posit_version.R +++ b/R/check_posit_version.R @@ -4,9 +4,13 @@ check_posit_version = function() { } else { cmd = system2("rstudio-server", args = "version", stdout = TRUE) posit_version = stringr::str_remove(cmd, " .*") - } - posit_version = stringr::str_remove(posit_version, "\\+[0-9]*") + posit_version = stringr::str_squish(posit_version) + + posit_version = stringr::str_extract( + posit_version, + "^20[0-9][0-9]\\.[0-9]?[0-9]\\.[0-9]?[0-9]" + ) audit.base::audit_posit_version(posit_version, type = "workbench") - return(posit_version) + posit_version } diff --git a/R/check_python.R b/R/check_python.R index 44e584c..0b50047 100644 --- a/R/check_python.R +++ b/R/check_python.R @@ -10,7 +10,7 @@ check_python_pip = R6::R6Class( #' @param debug_level See check() for details check = function(debug_level) { private$checker(python_pip_tests(debug_level)) - return(invisible(NULL)) + invisible(NULL) } ), private = list( @@ -33,7 +33,7 @@ check_python_reticulate = R6::R6Class( #' @param debug_level See check() for details check = function(debug_level) { private$checker(python_reticulate_tests(debug_level)) - return(invisible(NULL)) + invisible(NULL) } ), private = list( @@ -51,15 +51,21 @@ python_pip_tests = function(debug_level) { min_version = grepl("pip [2-3][0-9]", pip_version) stopifnot("Pip failed to install " = min_version) - numpy = processx::run("pip", args = c("install", "numpy", "--force-reinstall")) + numpy = processx::run( + "pip", + args = c("install", "numpy", "--force-reinstall") + ) withr::defer(processx::run("pip", args = c("uninstall", "numpy", "--yes"))) - has_installed = grepl(numpy$stdout, pattern = "Successfully installed") + has_installed = grepl( + numpy$stdout, + pattern = "Successfully installed", + fixed = TRUE + ) stopifnot("Pip failed to install " = has_installed) - return(invisible(TRUE)) + invisible(TRUE) } python_reticulate_tests = function(debug_level) { - if (!requireNamespace("reticulate", quietly = TRUE)) { utils::install.packages("reticulate") withr::defer(utils::remove.packages("reticulate")) @@ -67,5 +73,5 @@ python_reticulate_tests = function(debug_level) { reticulate::py_run_string("x=2+2") stopifnot("Reticulate error " = reticulate::py$x == 4) - return(invisible(TRUE)) + invisible(TRUE) } diff --git a/R/check_quarto.R b/R/check_quarto.R index 162f9d2..e6569b8 100644 --- a/R/check_quarto.R +++ b/R/check_quarto.R @@ -6,7 +6,11 @@ #' @rawNamespace export(check_quarto_rsvg_convert) NULL types = c("beamer", "docx", "html", "observable", "pdf", "rsvg_convert") -longs = paste0("Checking that quarto can render a document (type: `", types, "`)") +longs = paste0( + "Checking that quarto can render a document (type: `", + types, + "`)" +) longs[6] = "Checking that quarto can render SVG image within a PDF" for (i in seq_along(types)) { @@ -17,12 +21,17 @@ for (i in seq_along(types)) { inherit = audit.base::base_check, public = list( check = function(debug_level) { - quarto_dir = system.file("extdata", private$group, private$short, - package = "audit.base", mustWork = TRUE) + quarto_dir = system.file( + "extdata", + private$group, + private$short, + package = "audit.base", + mustWork = TRUE + ) private$checker( - render_quarto(quarto_dir, debug_level = debug_level)) - - return(invisible(NULL)) + render_quarto(quarto_dir, debug_level = debug_level) + ) + invisible(NULL) } ), private = list( @@ -39,17 +48,21 @@ render_quarto = function(quarto_dir, debug_level) { suppress = audit.base::get_suppress(debug_level) #nolint tmp_dir = file.path(tempdir(), "quarto") - on.exit({if (fs::dir_exists(tmp_dir)) fs::dir_delete(tmp_dir)}) #nolint + on.exit({ + if (fs::dir_exists(tmp_dir)) fs::dir_delete(tmp_dir) + }) #nolint dir.create(tmp_dir, showWarnings = FALSE) - lapply(list.files(quarto_dir, full.names = TRUE), - function(f) file.copy(f, tmp_dir)) + lapply(list.files(quarto_dir, full.names = TRUE), function(f) { + file.copy(f, tmp_dir) + }) qmd_filepath = file.path(tmp_dir, "index.qmd") - quarto::quarto_render(input = qmd_filepath, - execute_dir = tmp_dir, - quiet = (debug_level == 0), - cache = FALSE, - as_job = FALSE + quarto::quarto_render( + input = qmd_filepath, + execute_dir = tmp_dir, + quiet = (debug_level == 0), + cache = FALSE, + as_job = FALSE ) - return(invisible(TRUE)) + invisible(TRUE) } diff --git a/R/check_rmd.R b/R/check_rmd.R index 8c843e6..9bc2d69 100644 --- a/R/check_rmd.R +++ b/R/check_rmd.R @@ -10,40 +10,52 @@ #' @aliases check_rmd_word check_rmd_html check_rmd_pdf types = c("word", "html", "pdf") for (type in types) { - - assign(paste0("check_rmd_", type), R6::R6Class( + assign( paste0("check_rmd_", type), - inherit = audit.base::base_check, - public = list( - check = function(debug_level) { - rmd_dir = system.file("extdata", private$group, private$short, - package = "audit.base", mustWork = TRUE) - private$checker( - render_rmd(rmd_dir, debug_level = debug_level)) + R6::R6Class( + paste0("check_rmd_", type), + inherit = audit.base::base_check, + public = list( + check = function(debug_level) { + rmd_dir = system.file( + "extdata", + private$group, + private$short, + package = "audit.base", + mustWork = TRUE + ) + private$checker( + render_rmd(rmd_dir, debug_level = debug_level) + ) - return(invisible(NULL)) - } - ), - private = list( - context = paste("Rendering", type), - short = type, - group = "render_rmd", - long = paste0("Checking that Rmarkdown can render a document (type: `", type, "`)") + invisible(NULL) + } + ), + private = list( + context = paste("Rendering", type), + short = type, + group = "render_rmd", + long = paste0( + "Checking that Rmarkdown can render a document (type: `", + type, + "`)" + ) + ) ) - )) - + ) } render_rmd = function(rmd_dir, debug_level) { tmp_dir = file.path(tempdir(), "rmd") - on.exit({if (fs::dir_exists(tmp_dir)) fs::dir_delete(tmp_dir)}) #nolint + on.exit({ + if (fs::dir_exists(tmp_dir)) fs::dir_delete(tmp_dir) + }) #nolint dir.create(tmp_dir, showWarnings = FALSE) - lapply(list.files(rmd_dir, full.names = TRUE), - function(f) file.copy(f, tmp_dir)) + lapply(list.files(rmd_dir, full.names = TRUE), function(f) { + file.copy(f, tmp_dir) + }) - rmarkdown::render(file.path(tmp_dir, "index.Rmd"), - quiet = (debug_level == 0) - ) - return(invisible(TRUE)) + rmarkdown::render(file.path(tmp_dir, "index.Rmd"), quiet = (debug_level == 0)) + TRUE } diff --git a/R/check_versions.R b/R/check_versions.R index a4af5c8..69e8d2c 100644 --- a/R/check_versions.R +++ b/R/check_versions.R @@ -13,8 +13,10 @@ check_versions = function(debug_level) { quarto_vers = fs::dir_ls(quarto_dir, type = "directory", regexp = regexpr) versions = stringr::str_extract(c(r_vers, py_vers, quarto_vers), regexpr) - software = rep(c("r", "python", "quarto"), - c(length(r_vers), length(py_vers), length(quarto_vers))) + software = rep( + c("r", "python", "quarto"), + c(length(r_vers), length(py_vers), length(quarto_vers)) + ) installed = tibble::tibble(installed_version = versions, software) audit.base::augment_installed(installed) diff --git a/R/create_config.R b/R/create_config.R index 22a898f..b737051 100644 --- a/R/create_config.R +++ b/R/create_config.R @@ -16,5 +16,7 @@ #' * force: overwrite existing file #' * error: if a config file exists, raise an error #' @export -create_config = audit.base::create_config(file = "config-uat-psw.yml", - pkg_name = "jrHealthCheckWorkbench") +create_config = audit.base::create_config( + file = "config-uat-psw.yml", + pkg_name = "jrHealthCheckWorkbench" +) diff --git a/R/import-from.R b/R/import-from.R deleted file mode 100644 index 0312a8c..0000000 --- a/R/import-from.R +++ /dev/null @@ -1,2 +0,0 @@ -#' @importFrom dplyr %>% -NULL diff --git a/README.Rmd b/README.Rmd index 950ad17..e604d00 100644 --- a/README.Rmd +++ b/README.Rmd @@ -13,7 +13,7 @@ knitr::opts_chunk$set( ) ``` -# audit.connect +# audit.workbench [![R-CMD-check](https://github.com/jumpingrivers/audit.workbench/actions/workflows/R-CMD-check.yaml/badge.svg)](https://github.com/jumpingrivers/audit.workbench/actions/workflows/R-CMD-check.yaml) @@ -26,9 +26,10 @@ This checks that Posit Workbench has been correctly installed. To install the R package, run ```{r, eval = FALSE} -install.packages('audit.workbench', - repos = c('https://jumpingrivers.r-universe.dev', - 'https://cloud.r-project.org')) +install.packages( + "audit.workbench", + repos = c('https://jumpingrivers.r-universe.dev', options("repos")$repos) +) ``` ## Usage @@ -39,4 +40,3 @@ Running the test is straightforward library("audit.workbench") check(server = "https://www.server.name/") ``` - diff --git a/inst/extdata/report/report.qmd b/inst/extdata/report/report.qmd index 825a393..ae1c527 100644 --- a/inst/extdata/report/report.qmd +++ b/inst/extdata/report/report.qmd @@ -1,6 +1,6 @@ --- title: "Posit Workbench Audit" -format: +format: html: self-contained: true theme: flatly @@ -39,7 +39,7 @@ server_name = stringr::str_remove_all(audit_details$server, "(^http?s://|/$)") ## Overview (`r server_name`) -This audit was run by user `r glue::glue("{audit_details$name}")`, using {audit.workbench} R package (version `r audit_details$version`). +This audit was run by user `r glue::glue("{audit_details$name}")`, using {audit.workbench} R package (version `r audit_details$version`). `r audit.base::get_quarto_posit_version_msg(out, "workbench")` @@ -47,29 +47,37 @@ This audit was run by user `r glue::glue("{audit_details$name}")`, using {audit. This audit examines the server headings of the Posit server (or the server sitting in front of Posit). It is important to note, that there may be cases where you may want to deviate from setting these -headings. However, this is the exception and not the rule. +headings. However, this is the exception and not the rule. The headings listed below follow the recommendations of [securityheaders.com](https://serverheaders.com/) and (to a certain extent) Mozilla. Where the heading has not been set, we provide links to documentation. ```{r} #| echo: false headers = audit.base::get_quarto_server_header(out) -gt::gt(headers) %>% - gt::cols_label("header" = "Header", message = "Information") %>% - gt::cols_align("left") %>% - gt::cols_hide("status") %>% - gt::tab_row_group(label = "Looks good", rows = which(headers$status == "OK")) %>% - gt::tab_row_group(label = "To investigate", rows = which(headers$status != "OK")) %>% - gtExtras::gt_merge_stack(col1 = "message", col2 = "value", - palette = c("grey10", "grey50"), - font_weight = c("normal", "normal"), - small_cap = FALSE +gt::gt(headers) |> + gt::cols_label("header" = "Header", message = "Information") |> + gt::cols_align("left") |> + gt::cols_hide("status") |> + gt::tab_row_group( + label = "Looks good", + rows = which(headers$status == "OK") + ) |> + gt::tab_row_group( + label = "To investigate", + rows = which(headers$status != "OK") + ) |> + gtExtras::gt_merge_stack( + col1 = "message", + col2 = "value", + palette = c("grey10", "grey50"), + font_weight = c("normal", "normal"), + small_cap = FALSE ) ``` ## System Dependencies -Posit allows users to push dashboards and markdown documents. +Posit allows users to push dashboards and markdown documents. However, these applications contain R packages that have system level dependencies. This check tries to determine which R packages would fail to install. @@ -81,42 +89,54 @@ sys_deps = audit.base::get_quarto_sys_deps(out) ### Summary -There are `r nrow(sys_deps)` R packages that can't be installed, due to +There are `r nrow(sys_deps)` R packages that can't be installed, due to `r sum(sys_deps$n)` missing system dependencies. ```{r} #| echo: false -gt::gt(sys_deps) %>% - gt::cols_label("sys_libs" = "System Library", - "pkg" = "R Package") %>% - gt::cols_align("left") %>% - gt::cols_hide("n") %>% - gt::tab_style(style = gt::cell_text(v_align = "top"), - locations = gt::cells_body(columns = sys_libs)) +gt::gt(sys_deps) |> + gt::cols_label("sys_libs" = "System Library", "pkg" = "R Package") |> + gt::cols_align("left") |> + gt::cols_hide("n") |> + gt::tab_style( + style = gt::cell_text(v_align = "top"), + locations = gt::cells_body(columns = sys_libs) + ) ``` ## Software Versions Posit contains multiple versions of R, Python and Quarto. -This audit compares the installed version, to the latest version. +This audit compares the installed version, to the latest version. We've highlighted any older versions. ```{r} #| echo: false software = audit.base::get_quarto_software_versions(out) -gt::gt(software) %>% - gt::cols_label("version" = "Latest version", - "installed_version" = "Installed version") %>% - gt::cols_align("right") %>% - gt::cols_hide(c("software", "upgrade")) %>% - - gt::tab_row_group(label = "R", rows = which(.data$software == "r")) %>% - gt::tab_row_group(label = "Python", rows = which(.data$software == "python")) %>% - gt::tab_row_group(label = "Quarto", rows = which(.data$software == "quarto")) %>% - - gtExtras::gt_highlight_rows(rows = which(.data$upgrade), font_color = "white", - fill = severe) +gt::gt(software) |> + gt::cols_label( + "version" = "Latest version", + "installed_version" = "Installed version" + ) |> + gt::cols_align("right") |> + gt::cols_hide(c("software", "upgrade")) |> + + gt::tab_row_group(label = "R", rows = which(.data$software == "r")) |> + gt::tab_row_group( + label = "Python", + rows = which(.data$software == "python") + ) |> + gt::tab_row_group( + label = "Quarto", + rows = which(.data$software == "quarto") + ) |> + + gtExtras::gt_highlight_rows( + rows = which(.data$upgrade), + font_color = "white", + fill = severe + ) ``` ## Deployments @@ -127,16 +147,17 @@ The test determines if the application has been successful launched. ```{r} #| echo: false deploy = audit.base::get_quarto_deploy(out) -gt::gt(deploy) %>% - gt::cols_label("context" = "Deployment", - "time_taken" = "Time (secs)") %>% - gt::cols_align("right", "time_taken") %>% - gt::cols_hide(c("passed", "group", "short")) %>% - gt::tab_row_group(label = "Failed", rows = which(!deploy$passed)) %>% - gt::tab_row_group(label = "Looks good", rows = which(deploy$passed)) %>% - gtExtras::gt_merge_stack(col1 = "context", col2 = "type", - palette = c("grey10", "grey50"), - font_weight = c("normal", "normal"), - small_cap = FALSE +gt::gt(deploy) |> + gt::cols_label("context" = "Deployment", "time_taken" = "Time (secs)") |> + gt::cols_align("right", "time_taken") |> + gt::cols_hide(c("passed", "group", "short")) |> + gt::tab_row_group(label = "Failed", rows = which(!deploy$passed)) |> + gt::tab_row_group(label = "Looks good", rows = which(deploy$passed)) |> + gtExtras::gt_merge_stack( + col1 = "context", + col2 = "type", + palette = c("grey10", "grey50"), + font_weight = c("normal", "normal"), + small_cap = FALSE ) ```