From 3ea98c65e4432665758b0095524f4bd6c0136236 Mon Sep 17 00:00:00 2001 From: hsonne Date: Tue, 13 Jun 2023 10:41:26 +0200 Subject: [PATCH 01/14] Add script that allows to delete workflow runs --- inst/extdata/delete-workflow-runs.R | 78 +++++++++++++++++++++++++++++ 1 file changed, 78 insertions(+) create mode 100644 inst/extdata/delete-workflow-runs.R diff --git a/inst/extdata/delete-workflow-runs.R b/inst/extdata/delete-workflow-runs.R new file mode 100644 index 0000000..d1f18df --- /dev/null +++ b/inst/extdata/delete-workflow-runs.R @@ -0,0 +1,78 @@ +if (FALSE) +{ + token <- Sys.getenv("GITHUB_PAT") + + repo <- "wasserportal" + #workflow <- "R-CMD-check.yaml" + #workflow <- "pkgdown.yaml" + + # Get link to last page of runs + url_link <- url_runs(repo, workflow) %>% + get_response(token) %>% + get_link_to_last() + + url_link + + urls_last_runs <- url_link %>% + get_response(token) %>% + httr::content("parsed") %>% + kwb.utils::selectElements("workflow_runs") %>% + sapply(kwb.utils::selectElements, "url") + + urls_last_runs + + delete_runs(urls_last_runs, token) +} + +`%>%` <- magrittr::`%>%` + +# url_runs --------------------------------------------------------------------- +url_runs <- function(repo, workflow) +{ + sprintf( + "https://api.github.com/repos/kwb-r/%s/actions/workflows/%s/runs", + repo, + workflow + ) +} + +# get_response ----------------------------------------------------------------- +get_response <- function(url, token) +{ + httr::GET(url, headers = list( + Authorization = paste("token", token) + )) +} + +# get_link_to_last ------------------------------------------------------------- +get_link_to_last <- function(response) +{ + links <- response %>% + httr::headers() %>% + kwb.utils::selectElements("link") %>% + strsplit(",") %>% + `[[`(1L) + + link <- grep("rel=\"last\"", links, value = TRUE) + + gsub("^\\s*<|>;.*$", "", link) +} + +# delete_runs ------------------------------------------------------------------ +delete_runs <- function(urls, token) +{ + sapply(urls, function(url) { + + response <- kwb.utils::catAndRun( + paste("DELETE", url), + httr::DELETE( + url, + httr::add_headers( + Authorization = paste0("token ", token) + ) + ) + ) + + httr::status_code(response) + }) +} From 6fd95e6034267994ac976606916a159203a24bf5 Mon Sep 17 00:00:00 2001 From: hsonne Date: Sat, 8 Jul 2023 13:21:46 +0200 Subject: [PATCH 02/14] Improve script to delete latest workflow runs --- inst/extdata/delete-workflow-runs.R | 147 +++++++++++++++++----------- 1 file changed, 90 insertions(+), 57 deletions(-) diff --git a/inst/extdata/delete-workflow-runs.R b/inst/extdata/delete-workflow-runs.R index d1f18df..f320b51 100644 --- a/inst/extdata/delete-workflow-runs.R +++ b/inst/extdata/delete-workflow-runs.R @@ -1,78 +1,111 @@ if (FALSE) { - token <- Sys.getenv("GITHUB_PAT") - - repo <- "wasserportal" - #workflow <- "R-CMD-check.yaml" - #workflow <- "pkgdown.yaml" - - # Get link to last page of runs - url_link <- url_runs(repo, workflow) %>% - get_response(token) %>% - get_link_to_last() - - url_link - - urls_last_runs <- url_link %>% - get_response(token) %>% - httr::content("parsed") %>% - kwb.utils::selectElements("workflow_runs") %>% - sapply(kwb.utils::selectElements, "url") - - urls_last_runs - - delete_runs(urls_last_runs, token) + run_info <- get_info_on_last_workflow_runs( + repo = "status", + per_page = 100L, + "name" + ) + + nrow(run_info) + + range(run_info$run_started_at) + + delete_runs(urls = run_info$url) } `%>%` <- magrittr::`%>%` -# url_runs --------------------------------------------------------------------- -url_runs <- function(repo, workflow) +# get_info_on_last_workflow_runs ----------------------------------------------- +get_info_on_last_workflow_runs <- function(repo, per_page = 30L, ...) { - sprintf( - "https://api.github.com/repos/kwb-r/%s/actions/workflows/%s/runs", - repo, - workflow + result <- get_workflow_runs(repo) + + page <- last_page(result$total_count, per_page) + + result <- get_workflow_runs(repo, per_page = per_page, page = page) + + x <- result$workflow_runs + + stopifnot(length(x) <= per_page) + + do.call(rbind, lapply(x, function(xx) { + as.data.frame(kwb.utils::selectElements(xx, c( + "url", + "run_started_at", + "status", + ... + ))) + })) +} + +# get_workflow_runs ------------------------------------------------------------ +get_workflow_runs <- function(repo, per_page = 30L, page = 1L) +{ + endpoints <- list( + runs = "/repos///actions/runs?", + runs_pars = "per_page=&page=", + api = "https://api.github.com", + owner = "KWB-R" ) + + # List workflow runs for a repository + response <- get_response( + url = kwb.utils::resolve( + "runs", + endpoints, + repo = repo, + per_page = per_page, + page = page + ) + ) + + httr::content(response) } # get_response ----------------------------------------------------------------- -get_response <- function(url, token) +get_response <- function(url, token = github_token(), ...) +{ + httr::GET(url, headers = create_header(token, ...)) +} + +# github_token ----------------------------------------------------------------- +github_token <- function() { - httr::GET(url, headers = list( - Authorization = paste("token", token) - )) + Sys.getenv("GITHUB_PAT") } -# get_link_to_last ------------------------------------------------------------- -get_link_to_last <- function(response) +# create_header ---------------------------------------------------------------- +create_header <- function(token, ...) { - links <- response %>% - httr::headers() %>% - kwb.utils::selectElements("link") %>% - strsplit(",") %>% - `[[`(1L) - - link <- grep("rel=\"last\"", links, value = TRUE) - - gsub("^\\s*<|>;.*$", "", link) + list( + Authorization = paste("token", token), + ... + ) +} + +# last_page -------------------------------------------------------------------- +last_page <- function(n_runs, per_page) +{ + ((n_runs - 1L) %/% per_page) + 1L } # delete_runs ------------------------------------------------------------------ -delete_runs <- function(urls, token) +delete_runs <- function(urls, token = github_token()) { - sapply(urls, function(url) { - - response <- kwb.utils::catAndRun( - paste("DELETE", url), - httr::DELETE( - url, - httr::add_headers( - Authorization = paste0("token ", token) - ) - ) + invisible(sapply(seq_along(urls), function(i) { + + url <- urls[i] + + kwb.utils::catAndRun( + sprintf("Deleting %d/%d: %s ", i, length(urls), url), + expr = { + config <- do.call(httr::add_headers, create_header(token)) + response <- httr::DELETE(url, config) + if (httr::status_code(response) != 204L) { + print(response) + stop("DELETE failed.") + } + } ) - - httr::status_code(response) - }) + })) } From 71b90f4bfb60d5146480ef90685b59cf1172944d Mon Sep 17 00:00:00 2001 From: hsonne Date: Sat, 8 Jul 2023 14:06:46 +0200 Subject: [PATCH 03/14] Print response in case of HTTP error --- inst/extdata/delete-workflow-runs.R | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/inst/extdata/delete-workflow-runs.R b/inst/extdata/delete-workflow-runs.R index f320b51..1728d15 100644 --- a/inst/extdata/delete-workflow-runs.R +++ b/inst/extdata/delete-workflow-runs.R @@ -1,11 +1,14 @@ if (FALSE) { run_info <- get_info_on_last_workflow_runs( - repo = "status", - per_page = 100L, - "name" + repo = "kwb.nextcloud", + per_page = 50L, + "name", + "conclusion" ) + View(run_info) + nrow(run_info) range(run_info$run_started_at) @@ -59,6 +62,10 @@ get_workflow_runs <- function(repo, per_page = 30L, page = 1L) ) ) + if (httr::status_code(response) == 403L) { + print(response) + } + httr::content(response) } From b6f4289f25db6db72ec7afb693bb0a020e54b279 Mon Sep 17 00:00:00 2001 From: hsonne Date: Sun, 5 May 2024 09:39:00 +0200 Subject: [PATCH 04/14] Try to avoid issue with stringi inst from source --- .github/workflows/R-CMD-check.yaml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/R-CMD-check.yaml b/.github/workflows/R-CMD-check.yaml index 1da97de..51a645a 100644 --- a/.github/workflows/R-CMD-check.yaml +++ b/.github/workflows/R-CMD-check.yaml @@ -42,6 +42,10 @@ jobs: - uses: r-lib/actions/setup-pandoc@v2 + - name: Try to avoid issue with stringi installation from source + if: runner.os == 'Windows' + run: install.packages("stringi", type = "win.binary") + - name: Query dependencies run: | install.packages('remotes') From c98bd8008f67bf18e8b76db852b62cd148d341df Mon Sep 17 00:00:00 2001 From: hsonne Date: Sun, 5 May 2024 09:42:39 +0200 Subject: [PATCH 05/14] Add missing "shell: Rscript {0}" --- .github/workflows/R-CMD-check.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/R-CMD-check.yaml b/.github/workflows/R-CMD-check.yaml index 51a645a..b32fc61 100644 --- a/.github/workflows/R-CMD-check.yaml +++ b/.github/workflows/R-CMD-check.yaml @@ -45,6 +45,7 @@ jobs: - name: Try to avoid issue with stringi installation from source if: runner.os == 'Windows' run: install.packages("stringi", type = "win.binary") + shell: Rscript {0} - name: Query dependencies run: | From 08875598bf8687ea029715c0fc729a1e2e0b33cb Mon Sep 17 00:00:00 2001 From: hsonne Date: Sun, 5 May 2024 09:54:04 +0200 Subject: [PATCH 06/14] Can stringi be installed separatedly? --- .github/workflows/R-CMD-check.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/R-CMD-check.yaml b/.github/workflows/R-CMD-check.yaml index b32fc61..e068031 100644 --- a/.github/workflows/R-CMD-check.yaml +++ b/.github/workflows/R-CMD-check.yaml @@ -42,9 +42,9 @@ jobs: - uses: r-lib/actions/setup-pandoc@v2 - - name: Try to avoid issue with stringi installation from source + - name: Try to avoid issue with stringi installation further down if: runner.os == 'Windows' - run: install.packages("stringi", type = "win.binary") + run: install.packages("stringi") shell: Rscript {0} - name: Query dependencies From 56ac274898c36c2e3eac56a30feb8ed65aed4db6 Mon Sep 17 00:00:00 2001 From: testuser Date: Sat, 18 May 2024 07:52:11 +0200 Subject: [PATCH 07/14] Get rid of dependency on stringr instead, use: - the basic string manipulation functions - kwb.utils::extractSubstring() - basename(), dirname() add helper function: - email_kwb() In the vignette, simply use ``` for text blocks that do not represent R code but console outputs --- DESCRIPTION | 3 +-- NAMESPACE | 5 ---- R/.add_authors.R | 35 ++++++++++--------------- R/create_pkg_dir.R | 15 +++++------ R/helper.R | 19 +++++++++----- R/use_description.R | 11 +++----- R/use_gitlab_ci.R | 7 ++--- R/use_mit_license.R | 54 +++++++++++++++++++-------------------- R/use_pkg.R | 7 ++--- tests/testthat/.gitignore | 2 ++ tests/testthat/helper.R | 28 +++++++++++++------- vignettes/tutorial.Rmd | 16 +++++------- 12 files changed, 97 insertions(+), 105 deletions(-) create mode 100644 tests/testthat/.gitignore diff --git a/DESCRIPTION b/DESCRIPTION index 5d19095..02bc12b 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -35,7 +35,6 @@ Imports: processx, rematch2, sessioninfo, - stringr, usethis, withr, yaml @@ -53,4 +52,4 @@ Remotes: ByteCompile: true Encoding: UTF-8 LazyData: true -RoxygenNote: 7.2.1 +RoxygenNote: 7.3.1 diff --git a/NAMESPACE b/NAMESPACE index 2704fe2..2f46bfa 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -64,15 +64,10 @@ importFrom(pkgdown,build_site) importFrom(processx,run) importFrom(rematch2,re_match) importFrom(sessioninfo,package_info) -importFrom(stringr,str_detect) -importFrom(stringr,str_remove) -importFrom(stringr,str_replace) -importFrom(stringr,str_split) importFrom(tools,toTitleCase) importFrom(usethis,use_description) importFrom(usethis,use_git_ignore) importFrom(usethis,use_mit_license) importFrom(usethis,use_pkgdown) importFrom(usethis,use_template) -importFrom(utils,tail) importFrom(withr,with_dir) diff --git a/R/.add_authors.R b/R/.add_authors.R index bb92833..7902bcc 100644 --- a/R/.add_authors.R +++ b/R/.add_authors.R @@ -79,7 +79,7 @@ add_authors <- function(author_meta, role = "ctb", path = getwd()) #' @export #' @importFrom purrr transpose convert_author_metadata_tolist <- function( - author_metadata_df = create_author_metadata_from_orcid() + author_metadata_df = create_author_metadata_from_orcid() ) { setNames( @@ -94,31 +94,24 @@ convert_author_metadata_tolist <- function( #' @param orcids named character vector with ORCIDs and names correspondig to #' to "given_name family name" (defaults: kwb.orcid::get_kwb_orcids()) #' @importFrom kwb.orcid get_kwb_orcids -#' @importFrom stringr str_trim str_split -#' @importFrom magrittr %>% +#' @importFrom kwb.utils extractSubstring setColumns #' @return data frame with required metadata for R package DESCRIPTION as #' required by desc::desc_add_author() #' @export create_author_metadata_from_orcid <- function( - orcids = kwb.orcid::get_kwb_orcids() + orcids = kwb.orcid::get_kwb_orcids() ) { - orc_ids <- orcids[order(orcids)] - orc_names <- names(orcids) + orc_ids <- sort(orcids) - orc_names_matrix <- orc_names %>% - stringr::str_trim() %>% - stringr::str_split(pattern = "\\s+", simplify = TRUE, n = 2) - - kwb.utils::noFactorDataFrame( - given = orc_names_matrix[,1], - family = orc_names_matrix[,2], - email = sprintf( - "%s.%s@kompetenz-wasser.de", - tolower(orc_names_matrix[, 1]), - tolower(orc_names_matrix[, 2]) - ), - orcid = orc_ids, - row.names = NULL - ) + names(orcids) %>% + kwb.utils::extractSubstring( + pattern = "^\\s*(\\S+)\\s+(\\S+)\\s*$", + index = c(given = 1L, family = 2L) + ) %>% + kwb.utils::setColumns( + email = email_kwb(.[["given"]], .[["family"]]), + orcid = orc_ids, + dbg = FALSE + ) } diff --git a/R/create_pkg_dir.R b/R/create_pkg_dir.R index 567cba2..5bb228d 100644 --- a/R/create_pkg_dir.R +++ b/R/create_pkg_dir.R @@ -45,22 +45,21 @@ create_pkg_dir <- function(pkg_dir) #' @noRd #' @keywords internal -#' @importFrom stringr str_split -#' @importFrom utils tail check_pkg_dir_nested <- function(pkg_dir) { - last_folders <- utils::tail(n = 2, as.character( - stringr::str_split(pkg_dir, pattern = "/", simplify = TRUE) - )) + leaf_folder <- basename(pkg_dir) + parent_folder <- basename(dirname(pkg_dir)) - if (last_folders[1] == last_folders[2]) clean_stop( - sprintf("Package skeleton for '%s' cannot be created, ", last_folders[2]), + if (parent_folder == leaf_folder) clean_stop( + sprintf("Package skeleton for '%s' cannot be created, ", leaf_folder), sprintf("as it would be nested in subfolder '%s'.\n\n", pkg_dir), "Workaround: specify a different 'root_dir' in function use_pkg_skeleton()" ) message(sprintf( - "%s is a valid 'root_dir' for pkg '%s'", pkg_dir, last_folders[2] + "%s is a valid 'root_dir' for pkg '%s'", + pkg_dir, + leaf_folder )) pkg_dir diff --git a/R/helper.R b/R/helper.R index 9837341..c39ed22 100644 --- a/R/helper.R +++ b/R/helper.R @@ -4,6 +4,16 @@ clean_stop <- function(...) stop(..., call. = FALSE) } +# email_kwb -------------------------------------------------------------------- +email_kwb <- function( + given, + family, + full_name = paste0(given, family, sep = ".") +) +{ + paste0(tolower(full_name), "@kompetenz-wasser.de") +} + # get_pkgname ------------------------------------------------------------------ #' Helper Function: Get Package Name @@ -121,7 +131,6 @@ path_to_git <- function() #' @param dbg print debug messages (default: TRUE) #' @return sets globally user.name and user.email in Git #' @export -#' @importFrom stringr str_replace set_github_user <- function( git_username = "kwb.pkgbuild::use_autopkgdown()", git_fullname = "kwb.pkgbuild::use_autopkgdown()", @@ -132,13 +141,9 @@ set_github_user <- function( dbg = TRUE ) { + # Compose KWB e-mail address if (is.null(git_email)) { - - # Replace space with dot - dot_name <- stringr::str_replace(git_fullname, "\\s+", ".") - - # Compose KWB e-mail address - git_email <- paste0(tolower(dot_name), "@kompetenz-wasser.de") + git_email <- email_kwb(full_name = gsub("\\s+", ".", git_fullname)) } git_exe <- git_check_if_windows(git_exe) diff --git a/R/use_description.R b/R/use_description.R index 1a776a2..e7a7a4b 100644 --- a/R/use_description.R +++ b/R/use_description.R @@ -16,7 +16,6 @@ #' @return writes DESCRIPTION file using usethis::use_description() with KWB #' style #' @importFrom usethis use_description -#' @importFrom stringr str_split #' @importFrom tools toTitleCase #' @export use_description <- function( @@ -37,13 +36,11 @@ use_description <- function( pkg$title <- tools::toTitleCase(pkg$title) - full_name <- stringr::str_split(string = author$name,pattern = "\\s+")[[1]] - author_name <- full_name[1] - author_surname <- full_name[2] + full_name <- strsplit(author$name, "\\s+")[[1L]] + author_name <- full_name[1L] + author_surname <- full_name[2L] - author_email <- sprintf( - '%s.%s@kompetenz-wasser.de', tolower(author_name), tolower(author_surname) - ) + author_email <- email_kwb(given = author_name, family = author_surname) author_comment <- if (is.null(author$orcid)) { "NULL" diff --git a/R/use_gitlab_ci.R b/R/use_gitlab_ci.R index 22f9433..9056728 100644 --- a/R/use_gitlab_ci.R +++ b/R/use_gitlab_ci.R @@ -68,7 +68,6 @@ use_gitlab_ci_blogdown <- function( #' https://github.com/KWB-R/kwb.pkgbuild" sets "KWB-R/kwb.pkgbuild" as #' "/") #' @return writes .gitlab-ci.yml -#' @importFrom stringr str_remove #' @importFrom desc desc_get #' @export @@ -76,10 +75,8 @@ use_gitlab_ci_pkgdown <- function( dest_dir = getwd(), yml_vector = gitlab_ci_template_pkgdown() ) { - repo <- stringr::str_remove(desc::desc_get("URL"), "^http(s)?://github.com/") - - yml_vector <- stringr::str_replace(yml_vector, "/", repo) - + owner_repo <- gsub("^http(s)?://github.com/", "", desc::desc_get("URL")) + yml_vector <- gsub("/", owner_repo, yml_vector) write_gitlab_ci(yml_vector, dest_dir = dest_dir, ignore = TRUE) } diff --git a/R/use_mit_license.R b/R/use_mit_license.R index f34f3c4..882fbd6 100644 --- a/R/use_mit_license.R +++ b/R/use_mit_license.R @@ -6,48 +6,48 @@ #' (default: "list(name = kwb.pkgbuild:::kwb_string(), start_year = NULL)") #' @return creates MIT licence file #' @importFrom usethis use_mit_license -#' @importFrom stringr str_detect #' @importFrom fs file_copy #' @importFrom kwb.utils catAndRun #' @export use_mit_license <- function( - copyright_holder = list(name = kwb_string(), start_year = NULL) + copyright_holder = list(name = kwb_string(), start_year = NULL) ) { - kwb.utils::catAndRun("Creating KWB MIT LICENSE/LICENSE.md files", - expr = { - usethis::use_mit_license(copyright_holder = copyright_holder$name)}) + kwb.utils::catAndRun("Creating KWB MIT LICENSE/LICENSE.md files", { + usethis::use_mit_license(copyright_holder = copyright_holder$name) + }) + this_year <- format(Sys.Date(), format = "%Y") - copyright_years <- ifelse(!is.null(copyright_holder$start_year), - sprintf("%s-%s", as.character(copyright_holder$start_year), - format(Sys.Date(), format = "%Y")), - format(Sys.Date(), format = "%Y")) + copyright_years <- ifelse( + is.null(copyright_holder$start_year), + this_year, + sprintf("%s-%s", as.character(copyright_holder$start_year), this_year) + ) - if (! is.null(copyright_holder$start_year)) { + if (is.null(copyright_holder$start_year)) { + return() + } - kwb.utils::catAndRun("Modifying start year in MIT LICENSE (CRAN version)", - expr = { - writeLines(text = sprintf("YEAR: %s\nCOPYRIGHT HOLDER: %s", - copyright_years, - copyright_holder$name), - con = "LICENSE") - }) + kwb.utils::catAndRun("Modifying start year in MIT LICENSE (CRAN version)", { + writeLines( + text = sprintf( + "YEAR: %s\nCOPYRIGHT HOLDER: %s", + copyright_years, + copyright_holder$name + ), + con = "LICENSE" + ) + }) - kwb.utils::catAndRun("Modifying start year in MIT LICENSE.md", - expr = { + kwb.utils::catAndRun("Modifying start year in MIT LICENSE.md", { lic_txt <- readLines("LICENSE.md") - index <- stringr::str_detect(lic_txt,pattern = "^Copyright\\s+\\(c\\)") - + index <- grep("^Copyright\\s+\\(c\\)", lic_txt) lic_txt[index] <- sprintf( "Copyright (c) %s %s", copyright_years, copyright_holder$name ) - - writeLines(lic_txt, "LICENSE.md")}) - - - } - + writeLines(lic_txt, "LICENSE.md") + }) } diff --git a/R/use_pkg.R b/R/use_pkg.R index 9ab845d..eff8939 100644 --- a/R/use_pkg.R +++ b/R/use_pkg.R @@ -26,7 +26,6 @@ #' "archived", "dormant", "questioning"), (default: "experiment") #' @return writes DESCRIPTION file using usethis::use_description() with KWB #' style -#' @importFrom stringr str_detect #' @importFrom fs dir_create #' @param auto_build_pkgdown prepare Travis for pkgdown::build_site() (default: #' FALSE), only possible if GITHUB repo already existing @@ -55,10 +54,8 @@ use_pkg <- function( copyright_holder_name = copyright_holder$name, funder = funder ) - # Create MIT LICENSE file - mit_licence <- stringr::str_detect(string = license, pattern = "MIT") - - if (mit_licence) { + # Create MIT LICENSE file if applicable + if (grepl("MIT", license)) { use_mit_license(copyright_holder) } diff --git a/tests/testthat/.gitignore b/tests/testthat/.gitignore new file mode 100644 index 0000000..9e5d89c --- /dev/null +++ b/tests/testthat/.gitignore @@ -0,0 +1,2 @@ +#ignore docs +docs diff --git a/tests/testthat/helper.R b/tests/testthat/helper.R index 8b0d8a2..710ede8 100644 --- a/tests/testthat/helper.R +++ b/tests/testthat/helper.R @@ -1,13 +1,23 @@ ## Helper for creating temporary R package -create_pkg_temp <- function() { -number <- sample(x = 1:10000000,size = 1) -root_dir <- paste0(stringr::str_replace_all(tempdir(),"\\\\", "/"), - sprintf("%d", number)) -pkg_name <- "testpkg" -pkg_dir <- file.path(root_dir, pkg_name) -kwb.pkgbuild::create_pkg_dir(pkg_dir) -withr::with_dir(pkg_dir, {kwb.pkgbuild::use_pkg_skeleton(pkg_name)}) -pkg_dir +create_pkg_temp <- function() +{ + number <- sample(x = 1:10000000, size = 1L) + + root_dir <- paste0( + kwb.utils::rStylePath(tempdir()), + sprintf("%d", number) + ) + + pkg_name <- "testpkg" + pkg_dir <- file.path(root_dir, pkg_name) + + kwb.pkgbuild::create_pkg_dir(pkg_dir) + + withr::with_dir(pkg_dir, { + kwb.pkgbuild::use_pkg_skeleton(pkg_name) + }) + + pkg_dir } # create_pkg_temp <- function(root_dir = tempdir()) { diff --git a/vignettes/tutorial.Rmd b/vignettes/tutorial.Rmd index 02bddeb..076f94a 100644 --- a/vignettes/tutorial.Rmd +++ b/vignettes/tutorial.Rmd @@ -59,7 +59,6 @@ packages <- setdiff(required, installed) # Install the packages from CRAN for (package in packages) { - install.packages(package, repos = "https://cloud.r-project.org") } ``` @@ -192,10 +191,10 @@ The package description needs three entries - **name**: name of the package - **title**: title of your R package (which is automatically converted to title -case with the function `tools::toTitleCase()`) + case with the function `tools::toTitleCase()`) -- **desc:** package description. Should be at least one sentence long and -needs to end with a period! +- **desc:** package description. Should be at least one sentence long and needs + to end with a period! ```{r} description <- list( @@ -301,7 +300,7 @@ possible problems (e.g. wrong documentation, missing package dependencies). In case of missing package dependencies as shown below these should be added to the [DESCRIPTION](http://r-pkgs.had.co.nz/description.html) file. -```{r eval = FALSE} +``` Namespace dependencies not required: 'fs' 'httr' 'stringr' 'usethis' 'yaml' See section 'The DESCRIPTION file' in the 'Writing R Extensions' manual. @@ -318,7 +317,7 @@ Namespace dependencies not required: 'fs' 'httr' 'stringr' 'usethis' 'yaml' This can be done using the function `usethis::use_package()` as shown below: -```{r eval = FALSE} +``` pkg_dependencies <- c('fs', 'httr', 'stringr', 'usethis', 'yaml') sapply(pkg_dependencies, usethis::use_package) @@ -338,7 +337,7 @@ sapply(pkg_dependencies, usethis::use_package) Subsequently you should re-click on the `Check` button again and it should finish without errors. -```{r eval = FALSE} +``` R CMD check results 0 errors | 0 warning | 0 note @@ -351,7 +350,7 @@ Now you are ready for building your R package by clicking on the `Install and Restart` button. A successful installation should finish with `Done` as shown below: -```{r eval = FALSE} +``` ** building package indices ** installing vignettes ** testing if installed package can be loaded @@ -395,7 +394,6 @@ wrapper function `kwb.pkgbuild::use_autopkgdown()`, which: - prepares Github Actions by: - + creating ".github/workflows/" with `kwb.pkgbuild::use_ghactions()` + creating an empty "gh-pages" branch with From 64f4519400c318d06dd1474a1d366ca09d481575 Mon Sep 17 00:00:00 2001 From: testuser Date: Sat, 18 May 2024 08:10:26 +0200 Subject: [PATCH 08/14] Try to get rid of R CMD check warnings --- .github/workflows/R-CMD-check.yaml | 2 +- NAMESPACE | 1 + R/deploy_site_github_with_extra_files.R | 4 ++-- R/helper.R | 4 ++++ R/use_badges.R | 2 +- R/use_codecov.R | 4 ++-- R/use_pkg_skeleton.R | 3 +-- 7 files changed, 12 insertions(+), 8 deletions(-) diff --git a/.github/workflows/R-CMD-check.yaml b/.github/workflows/R-CMD-check.yaml index e068031..d38adeb 100644 --- a/.github/workflows/R-CMD-check.yaml +++ b/.github/workflows/R-CMD-check.yaml @@ -62,7 +62,7 @@ jobs: restore-keys: ${{ runner.os }}-r-${{ matrix.config.r }}-3- - name: Install system dependencies - if: runner.os == 'Linux' + if: runner.os == 'Linux (no, try without!)' env: RHUB_PLATFORM: linux-x86_64-ubuntu-gcc run: | diff --git a/NAMESPACE b/NAMESPACE index 2f46bfa..f0630ef 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -70,4 +70,5 @@ importFrom(usethis,use_git_ignore) importFrom(usethis,use_mit_license) importFrom(usethis,use_pkgdown) importFrom(usethis,use_template) +importFrom(utils,getFromNamespace) importFrom(withr,with_dir) diff --git a/R/deploy_site_github_with_extra_files.R b/R/deploy_site_github_with_extra_files.R index 0120b6c..e8fe796 100644 --- a/R/deploy_site_github_with_extra_files.R +++ b/R/deploy_site_github_with_extra_files.R @@ -258,7 +258,7 @@ deploy_to_branch_with_extra_files <- function(pkg = ".", if (clean) { rule("Cleaning files from old site", line = 1) - pkgdown:::clean_site(pkg) + pkgdown::clean_site(pkg) } pkgdown::build_site(pkg, devel = FALSE, preview = FALSE, install = FALSE, ...) @@ -271,7 +271,7 @@ deploy_to_branch_with_extra_files <- function(pkg = ".", ) if (github_pages) { - pkgdown:::build_github_pages(pkg) + getFromNamespace("build_github_pages", "pkgdown")(pkg) } github_push(dest_dir, commit_message, remote, branch) diff --git a/R/helper.R b/R/helper.R index c39ed22..36907da 100644 --- a/R/helper.R +++ b/R/helper.R @@ -14,6 +14,10 @@ email_kwb <- function( paste0(tolower(full_name), "@kompetenz-wasser.de") } +# get_from_namespace ----------------------------------------------------------- +#' @importFrom utils getFromNamespace +get_from_namespace <- utils::getFromNamespace + # get_pkgname ------------------------------------------------------------------ #' Helper Function: Get Package Name diff --git a/R/use_badges.R b/R/use_badges.R index 9255450..d83ee98 100644 --- a/R/use_badges.R +++ b/R/use_badges.R @@ -140,7 +140,7 @@ use_badge_codecov <- function(repo = NULL, user = "KWB-R", domain = "github") #' @export use_badge_lifecycle <- function(stage = "experimental") { - stages <- usethis:::stages + stages <- getFromNamespace("stages", "usethis") stage <- match.arg(tolower(stage), names(stages)) kwb.utils::resolve( diff --git a/R/use_codecov.R b/R/use_codecov.R index cda178a..d824391 100644 --- a/R/use_codecov.R +++ b/R/use_codecov.R @@ -6,8 +6,8 @@ #' @export use_codecov <- function() { - usethis:::check_uses_github_actions() - usethis:::use_dependency("covr", "Suggests") + getFromNamespace("check_uses_github_actions", "usethis")() + getFromNamespace("use_dependency", "usethis")("covr", "Suggests") if (! usethis::use_template("codecov.yml", ignore = TRUE)) { return(invisible(FALSE)) diff --git a/R/use_pkg_skeleton.R b/R/use_pkg_skeleton.R index c981b85..a72072f 100644 --- a/R/use_pkg_skeleton.R +++ b/R/use_pkg_skeleton.R @@ -27,8 +27,7 @@ use_pkg_skeleton <- function(pkg_name) usethis::use_git_ignore(".Rproj.user") - if (usethis:::is_package()) { - + if (getFromNamespace("is_package", "usethis")()) { usethis::use_build_ignore(c( rproj_file, ".Rhistory", ".RData", ".Rproj.user" , ".here" )) From deeea38c33dd434694c466ccc1eb50cde4f1ec09 Mon Sep 17 00:00:00 2001 From: testuser Date: Sat, 18 May 2024 08:21:28 +0200 Subject: [PATCH 09/14] Remove the trial of a workaround --- .github/workflows/R-CMD-check.yaml | 5 ----- 1 file changed, 5 deletions(-) diff --git a/.github/workflows/R-CMD-check.yaml b/.github/workflows/R-CMD-check.yaml index d38adeb..62d8e39 100644 --- a/.github/workflows/R-CMD-check.yaml +++ b/.github/workflows/R-CMD-check.yaml @@ -42,11 +42,6 @@ jobs: - uses: r-lib/actions/setup-pandoc@v2 - - name: Try to avoid issue with stringi installation further down - if: runner.os == 'Windows' - run: install.packages("stringi") - shell: Rscript {0} - - name: Query dependencies run: | install.packages('remotes') From 89b1b532fa6139179247e0e7bcb5cd49986f9124 Mon Sep 17 00:00:00 2001 From: mrustl Date: Thu, 5 Sep 2024 10:45:58 +0200 Subject: [PATCH 10/14] Fix KWB logo --- R/use_pkgdown.R | 2 +- _pkgdown.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/R/use_pkgdown.R b/R/use_pkgdown.R index cc124a4..27bdae3 100644 --- a/R/use_pkgdown.R +++ b/R/use_pkgdown.R @@ -38,7 +38,7 @@ use_pkgdown <- function( authors <- c(authors, stats::setNames(nm = copyright_holder_name, list(list( href = "http://www.kompetenz-wasser.de", html = paste0( - "KWB") )))) } diff --git a/_pkgdown.yml b/_pkgdown.yml index e193371..f0d8678 100644 --- a/_pkgdown.yml +++ b/_pkgdown.yml @@ -10,7 +10,7 @@ authors: alt='Project FAKIN' width='72' /> Kompetenzzentrum Wasser Berlin gGmbH (KWB): href: https://www.kompetenz-wasser.de - html: KWB template: From b3ade603eabea1ae6d5017a5de4c2e817410191e Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 7 May 2026 06:40:36 +0000 Subject: [PATCH 11/14] Modernize GitHub Actions workflows The existing workflows used deprecated action versions (checkout@v2, cache@v1/v2, upload-artifact@main, r-lib/actions@master) and the ubuntu-20.04 runner that was retired in April 2025. They also depended on the archived r-hub/sysreqs package and contained a broken Linux sysdeps condition. Replace each workflow with the current r-lib/actions@v2 patterns, delegating dependency installation and caching to setup-r-dependencies, switching to ubuntu-latest, oldrel-1, and v4 checkout/upload-artifact, wiring pkgdown to deploy via the GitHub Pages action, and updating test-coverage to use codecov-action@v4 with cobertura output. Keep the inst/templates/ci_github-actions copies in sync so newly bootstrapped packages get the same workflows. --- .github/workflows/R-CMD-check.yaml | 58 ++++------------ .github/workflows/pkgdown.yaml | 59 ++++++++-------- .github/workflows/pr-commands.yaml | 68 ++++++++++++++----- .github/workflows/test-coverage.yaml | 55 +++++++++------ .../ci_github-actions/R-CMD-check.yaml | 57 ++++------------ inst/templates/ci_github-actions/pkgdown.yaml | 59 ++++++++-------- .../ci_github-actions/pr-commands.yaml | 68 ++++++++++++++----- .../ci_github-actions/test-coverage.yaml | 55 +++++++++------ 8 files changed, 258 insertions(+), 221 deletions(-) diff --git a/.github/workflows/R-CMD-check.yaml b/.github/workflows/R-CMD-check.yaml index 62d8e39..9f9476b 100644 --- a/.github/workflows/R-CMD-check.yaml +++ b/.github/workflows/R-CMD-check.yaml @@ -22,61 +22,33 @@ jobs: fail-fast: false matrix: config: - - {os: macOS-latest, r: 'release'} - - {os: ubuntu-20.04, r: 'release', rspm: "https://packagemanager.rstudio.com/cran/__linux__/focal/latest"} + - {os: macos-latest, r: 'release'} + - {os: ubuntu-latest, r: 'release'} - {os: windows-latest, r: 'devel'} - - {os: windows-latest, r: 'oldrel'} + - {os: windows-latest, r: 'oldrel-1'} - {os: windows-latest, r: 'release'} env: GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} - R_REMOTES_NO_ERRORS_FROM_WARNINGS: true - RSPM: ${{ matrix.config.rspm }} + R_KEEP_PKG_SOURCE: yes steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 + + - 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-pandoc@v2 - - - name: Query dependencies - run: | - install.packages('remotes') - saveRDS(remotes::dev_package_deps(dependencies = TRUE), "depends.Rds", version = 2) - shell: Rscript {0} - - - name: Cache R packages - if: runner.os != 'Windows' - uses: actions/cache@v1 + - uses: r-lib/actions/setup-r-dependencies@v2 with: - path: ${{ env.R_LIBS_USER }} - key: ${{ runner.os }}-r-${{ matrix.config.r }}-3-${{ hashFiles('depends.Rds') }} - restore-keys: ${{ runner.os }}-r-${{ matrix.config.r }}-3- - - - name: Install system dependencies - if: runner.os == 'Linux (no, try without!)' - env: - RHUB_PLATFORM: linux-x86_64-ubuntu-gcc - run: | - Rscript -e "remotes::install_github('r-hub/sysreqs')" - sysreqs=$(Rscript -e "cat(sysreqs::sysreq_commands('DESCRIPTION'))") - sudo -s eval "$sysreqs" - - name: Install dependencies - run: | - remotes::install_deps(dependencies = TRUE) - remotes::install_cran("rcmdcheck") - shell: Rscript {0} - - - name: Check - run: rcmdcheck::rcmdcheck(args = "--no-manual", error_on = "warning", check_dir = "check") - shell: Rscript {0} + extra-packages: any::rcmdcheck + needs: check - - name: Upload check results - if: failure() - uses: actions/upload-artifact@main + - uses: r-lib/actions/check-r-package@v2 with: - name: ${{ runner.os }}-r${{ matrix.config.r }}-results - path: check + upload-snapshots: true + args: 'c("--no-manual", "--as-cran")' diff --git a/.github/workflows/pkgdown.yaml b/.github/workflows/pkgdown.yaml index 3b2a357..2d703f6 100644 --- a/.github/workflows/pkgdown.yaml +++ b/.github/workflows/pkgdown.yaml @@ -4,48 +4,49 @@ on: - main - master - dev + pull_request: + branches: + - main + - master + - dev + release: + types: [published] + workflow_dispatch: name: pkgdown jobs: pkgdown: - runs-on: windows-latest + runs-on: ubuntu-latest + # Only restrict concurrency for non-PR jobs + concurrency: + group: pkgdown-${{ github.event_name != 'pull_request' || github.run_id }} env: - CURL_SSL_BACKEND: "openssl" GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} + permissions: + contents: write steps: - - uses: actions/checkout@v2 - - - uses: r-lib/actions/setup-r@v2 + - uses: actions/checkout@v4 - uses: r-lib/actions/setup-pandoc@v2 - - 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} + - uses: r-lib/actions/setup-r@v2 + with: + use-public-rspm: true - - name: Cache R packages - uses: actions/cache@v2 + - uses: r-lib/actions/setup-r-dependencies@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- + extra-packages: any::pkgdown, local::. + needs: website - - name: Install dependencies - run: | - remotes::install_deps(dependencies = TRUE) - install.packages("pkgdown", type = "binary") + - name: Build site + run: pkgdown::build_site_github_pages(new_process = FALSE, install = FALSE) shell: Rscript {0} - - name: Install package - run: R CMD INSTALL . - shell: cmd - - - name: Deploy package - run: | - git config --local user.email "actions@github.com" - git config --local user.name "GitHub Actions" - Rscript -e 'pkgdown::deploy_to_branch(new_process = FALSE)' + - name: Deploy to GitHub pages + if: github.event_name != 'pull_request' + uses: JamesIves/github-pages-deploy-action@v4.5.0 + with: + clean: false + branch: gh-pages + folder: docs diff --git a/.github/workflows/pr-commands.yaml b/.github/workflows/pr-commands.yaml index 0d3cb71..33cfb6c 100644 --- a/.github/workflows/pr-commands.yaml +++ b/.github/workflows/pr-commands.yaml @@ -1,51 +1,85 @@ on: issue_comment: types: [created] + name: Commands + jobs: document: - if: startsWith(github.event.comment.body, '/document') + if: ${{ github.event.issue.pull_request && startsWith(github.event.comment.body, '/document') }} name: document - runs-on: macOS-latest + runs-on: ubuntu-latest env: GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} + permissions: + contents: write + pull-requests: write steps: - - uses: actions/checkout@v2 - - uses: r-lib/actions/pr-fetch@master + - uses: actions/checkout@v4 + + - uses: r-lib/actions/pr-fetch@v2 with: repo-token: ${{ secrets.GITHUB_TOKEN }} - - uses: r-lib/actions/setup-r@master - - name: Install dependencies - run: Rscript -e 'install.packages(c("remotes", "roxygen2"))' -e 'remotes::install_deps(dependencies = TRUE)' + + - uses: r-lib/actions/setup-r@v2 + with: + use-public-rspm: true + + - uses: r-lib/actions/setup-r-dependencies@v2 + with: + extra-packages: any::roxygen2 + needs: pr-document + - name: Document - run: Rscript -e 'roxygen2::roxygenise()' + run: roxygen2::roxygenise() + shell: Rscript {0} + - name: commit run: | + git config --local user.name "$GITHUB_ACTOR" + git config --local user.email "$GITHUB_ACTOR@users.noreply.github.com" git add man/\* NAMESPACE git commit -m 'Document' - - uses: r-lib/actions/pr-push@master + + - uses: r-lib/actions/pr-push@v2 with: repo-token: ${{ secrets.GITHUB_TOKEN }} + style: - if: startsWith(github.event.comment.body, '/style') + if: ${{ github.event.issue.pull_request && startsWith(github.event.comment.body, '/style') }} name: style - runs-on: macOS-latest + runs-on: ubuntu-latest env: GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} + permissions: + contents: write + pull-requests: write steps: - - uses: actions/checkout@v2 - - uses: r-lib/actions/pr-fetch@master + - uses: actions/checkout@v4 + + - uses: r-lib/actions/pr-fetch@v2 with: repo-token: ${{ secrets.GITHUB_TOKEN }} - - uses: r-lib/actions/setup-r@master + + - uses: r-lib/actions/setup-r@v2 + with: + use-public-rspm: true + - name: Install dependencies - run: Rscript -e 'install.packages("styler")' + run: install.packages("styler") + shell: Rscript {0} + - name: Style - run: Rscript -e 'styler::style_pkg()' + run: styler::style_pkg() + shell: Rscript {0} + - name: commit run: | + git config --local user.name "$GITHUB_ACTOR" + git config --local user.email "$GITHUB_ACTOR@users.noreply.github.com" git add \*.R git commit -m 'Style' - - uses: r-lib/actions/pr-push@master + + - uses: r-lib/actions/pr-push@v2 with: repo-token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/test-coverage.yaml b/.github/workflows/test-coverage.yaml index 0f014df..254c6db 100644 --- a/.github/workflows/test-coverage.yaml +++ b/.github/workflows/test-coverage.yaml @@ -12,37 +12,50 @@ name: test-coverage jobs: test-coverage: - runs-on: windows-latest + runs-on: ubuntu-latest env: GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} + steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - uses: r-lib/actions/setup-r@v2 + with: + use-public-rspm: true - - uses: r-lib/actions/setup-pandoc@v2 + - uses: r-lib/actions/setup-r-dependencies@v2 + with: + extra-packages: any::covr, any::xml2 + needs: coverage - - name: Query dependencies + - name: Test coverage 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") + cov <- covr::package_coverage( + quiet = FALSE, + clean = FALSE, + install_path = file.path(normalizePath(Sys.getenv("RUNNER_TEMP"), winslash = "/"), "package") + ) + covr::to_cobertura(cov) shell: Rscript {0} - - name: Cache R packages - uses: actions/cache@v1 + - uses: codecov/codecov-action@v4 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 dependencies + fail_ci_if_error: ${{ github.event_name != 'pull_request' && true || false }} + file: ./cobertura.xml + plugin: noop + disable_search: true + token: ${{ secrets.CODECOV_TOKEN }} + + - name: Show testthat output + if: always() run: | - install.packages(c("remotes")) - remotes::install_deps(dependencies = TRUE) - remotes::install_cran("covr") - shell: Rscript {0} + ## -------------------------------------------------------------------- + find '${{ runner.temp }}/package' -name 'testthat.Rout*' -exec cat '{}' \; || true + shell: bash - - name: Test coverage - run: covr::codecov() - shell: Rscript {0} + - name: Upload test results + if: failure() + uses: actions/upload-artifact@v4 + with: + name: coverage-test-failures + path: ${{ runner.temp }}/package diff --git a/inst/templates/ci_github-actions/R-CMD-check.yaml b/inst/templates/ci_github-actions/R-CMD-check.yaml index 20bd49a..9f9476b 100644 --- a/inst/templates/ci_github-actions/R-CMD-check.yaml +++ b/inst/templates/ci_github-actions/R-CMD-check.yaml @@ -22,62 +22,33 @@ jobs: fail-fast: false matrix: config: - - {os: macOS-latest, r: 'release'} - - {os: ubuntu-20.04, r: 'release', rspm: "https://packagemanager.rstudio.com/cran/__linux__/focal/latest"} + - {os: macos-latest, r: 'release'} + - {os: ubuntu-latest, r: 'release'} - {os: windows-latest, r: 'devel'} - - {os: windows-latest, r: 'oldrel'} + - {os: windows-latest, r: 'oldrel-1'} - {os: windows-latest, r: 'release'} env: GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} - R_REMOTES_NO_ERRORS_FROM_WARNINGS: true - RSPM: ${{ matrix.config.rspm }} + R_KEEP_PKG_SOURCE: yes steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 + + - 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-pandoc@v2 - - - name: Query dependencies - run: | - install.packages('remotes') - saveRDS(remotes::dev_package_deps(dependencies = TRUE), "depends.Rds", version = 2) - shell: Rscript {0} - - - name: Cache R packages - if: runner.os != 'Windows' - uses: actions/cache@v1 + - uses: r-lib/actions/setup-r-dependencies@v2 with: - path: ${{ env.R_LIBS_USER }} - key: ${{ runner.os }}-r-${{ matrix.config.r }}-3-${{ hashFiles('depends.Rds') }} - restore-keys: ${{ runner.os }}-r-${{ matrix.config.r }}-3- - - - name: Install system dependencies - if: runner.os == 'Linux' - env: - RHUB_PLATFORM: linux-x86_64-ubuntu-gcc - run: | - Rscript -e "remotes::install_github('r-hub/sysreqs')" - sysreqs=$(Rscript -e "cat(sysreqs::sysreq_commands('DESCRIPTION'))") - sudo -s eval "$sysreqs" - - name: Install dependencies - run: | - remotes::install_deps(dependencies = TRUE) - remotes::install_cran("rcmdcheck") - shell: Rscript {0} - - - name: Check - run: rcmdcheck::rcmdcheck(args = "--no-manual", error_on = "warning", check_dir = "check") - shell: Rscript {0} + extra-packages: any::rcmdcheck + needs: check - - name: Upload check results - if: failure() - uses: actions/upload-artifact@main + - uses: r-lib/actions/check-r-package@v2 with: - name: ${{ runner.os }}-r${{ matrix.config.r }}-results - path: check + upload-snapshots: true + args: 'c("--no-manual", "--as-cran")' diff --git a/inst/templates/ci_github-actions/pkgdown.yaml b/inst/templates/ci_github-actions/pkgdown.yaml index ac3ba07..2d703f6 100644 --- a/inst/templates/ci_github-actions/pkgdown.yaml +++ b/inst/templates/ci_github-actions/pkgdown.yaml @@ -4,50 +4,49 @@ on: - main - master - dev + pull_request: + branches: + - main + - master + - dev + release: + types: [published] + workflow_dispatch: name: pkgdown jobs: pkgdown: - runs-on: windows-latest + runs-on: ubuntu-latest + # Only restrict concurrency for non-PR jobs + concurrency: + group: pkgdown-${{ github.event_name != 'pull_request' || github.run_id }} env: - CURL_SSL_BACKEND: "openssl" GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} + permissions: + contents: write steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 + + - uses: r-lib/actions/setup-pandoc@v2 - uses: r-lib/actions/setup-r@v2 with: use-public-rspm: true - - uses: r-lib/actions/setup-pandoc@v2 - - - 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 - uses: actions/cache@v2 + - uses: r-lib/actions/setup-r-dependencies@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- + extra-packages: any::pkgdown, local::. + needs: website - - name: Install dependencies - run: | - remotes::install_deps(dependencies = TRUE) - install.packages("pkgdown", type = "binary") + - name: Build site + run: pkgdown::build_site_github_pages(new_process = FALSE, install = FALSE) shell: Rscript {0} - - name: Install package - run: R CMD INSTALL . - shell: cmd - - - name: Deploy package - run: | - git config --local user.email "actions@github.com" - git config --local user.name "GitHub Actions" - Rscript -e 'pkgdown::deploy_to_branch(new_process = FALSE)' + - name: Deploy to GitHub pages + if: github.event_name != 'pull_request' + uses: JamesIves/github-pages-deploy-action@v4.5.0 + with: + clean: false + branch: gh-pages + folder: docs diff --git a/inst/templates/ci_github-actions/pr-commands.yaml b/inst/templates/ci_github-actions/pr-commands.yaml index 0d3cb71..33cfb6c 100644 --- a/inst/templates/ci_github-actions/pr-commands.yaml +++ b/inst/templates/ci_github-actions/pr-commands.yaml @@ -1,51 +1,85 @@ on: issue_comment: types: [created] + name: Commands + jobs: document: - if: startsWith(github.event.comment.body, '/document') + if: ${{ github.event.issue.pull_request && startsWith(github.event.comment.body, '/document') }} name: document - runs-on: macOS-latest + runs-on: ubuntu-latest env: GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} + permissions: + contents: write + pull-requests: write steps: - - uses: actions/checkout@v2 - - uses: r-lib/actions/pr-fetch@master + - uses: actions/checkout@v4 + + - uses: r-lib/actions/pr-fetch@v2 with: repo-token: ${{ secrets.GITHUB_TOKEN }} - - uses: r-lib/actions/setup-r@master - - name: Install dependencies - run: Rscript -e 'install.packages(c("remotes", "roxygen2"))' -e 'remotes::install_deps(dependencies = TRUE)' + + - uses: r-lib/actions/setup-r@v2 + with: + use-public-rspm: true + + - uses: r-lib/actions/setup-r-dependencies@v2 + with: + extra-packages: any::roxygen2 + needs: pr-document + - name: Document - run: Rscript -e 'roxygen2::roxygenise()' + run: roxygen2::roxygenise() + shell: Rscript {0} + - name: commit run: | + git config --local user.name "$GITHUB_ACTOR" + git config --local user.email "$GITHUB_ACTOR@users.noreply.github.com" git add man/\* NAMESPACE git commit -m 'Document' - - uses: r-lib/actions/pr-push@master + + - uses: r-lib/actions/pr-push@v2 with: repo-token: ${{ secrets.GITHUB_TOKEN }} + style: - if: startsWith(github.event.comment.body, '/style') + if: ${{ github.event.issue.pull_request && startsWith(github.event.comment.body, '/style') }} name: style - runs-on: macOS-latest + runs-on: ubuntu-latest env: GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} + permissions: + contents: write + pull-requests: write steps: - - uses: actions/checkout@v2 - - uses: r-lib/actions/pr-fetch@master + - uses: actions/checkout@v4 + + - uses: r-lib/actions/pr-fetch@v2 with: repo-token: ${{ secrets.GITHUB_TOKEN }} - - uses: r-lib/actions/setup-r@master + + - uses: r-lib/actions/setup-r@v2 + with: + use-public-rspm: true + - name: Install dependencies - run: Rscript -e 'install.packages("styler")' + run: install.packages("styler") + shell: Rscript {0} + - name: Style - run: Rscript -e 'styler::style_pkg()' + run: styler::style_pkg() + shell: Rscript {0} + - name: commit run: | + git config --local user.name "$GITHUB_ACTOR" + git config --local user.email "$GITHUB_ACTOR@users.noreply.github.com" git add \*.R git commit -m 'Style' - - uses: r-lib/actions/pr-push@master + + - uses: r-lib/actions/pr-push@v2 with: repo-token: ${{ secrets.GITHUB_TOKEN }} diff --git a/inst/templates/ci_github-actions/test-coverage.yaml b/inst/templates/ci_github-actions/test-coverage.yaml index 0f014df..254c6db 100644 --- a/inst/templates/ci_github-actions/test-coverage.yaml +++ b/inst/templates/ci_github-actions/test-coverage.yaml @@ -12,37 +12,50 @@ name: test-coverage jobs: test-coverage: - runs-on: windows-latest + runs-on: ubuntu-latest env: GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} + steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - uses: r-lib/actions/setup-r@v2 + with: + use-public-rspm: true - - uses: r-lib/actions/setup-pandoc@v2 + - uses: r-lib/actions/setup-r-dependencies@v2 + with: + extra-packages: any::covr, any::xml2 + needs: coverage - - name: Query dependencies + - name: Test coverage 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") + cov <- covr::package_coverage( + quiet = FALSE, + clean = FALSE, + install_path = file.path(normalizePath(Sys.getenv("RUNNER_TEMP"), winslash = "/"), "package") + ) + covr::to_cobertura(cov) shell: Rscript {0} - - name: Cache R packages - uses: actions/cache@v1 + - uses: codecov/codecov-action@v4 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 dependencies + fail_ci_if_error: ${{ github.event_name != 'pull_request' && true || false }} + file: ./cobertura.xml + plugin: noop + disable_search: true + token: ${{ secrets.CODECOV_TOKEN }} + + - name: Show testthat output + if: always() run: | - install.packages(c("remotes")) - remotes::install_deps(dependencies = TRUE) - remotes::install_cran("covr") - shell: Rscript {0} + ## -------------------------------------------------------------------- + find '${{ runner.temp }}/package' -name 'testthat.Rout*' -exec cat '{}' \; || true + shell: bash - - name: Test coverage - run: covr::codecov() - shell: Rscript {0} + - name: Upload test results + if: failure() + uses: actions/upload-artifact@v4 + with: + name: coverage-test-failures + path: ${{ runner.temp }}/package From 4cac6e6cf783b2143efe00821d38e003f04a6b9b Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 7 May 2026 06:47:54 +0000 Subject: [PATCH 12/14] Add optional Claude Code workflows and bump to v0.3.0 Mirror the Claude Code workflows used in kwb.raindrop into this repo and ship them as templates so consumers of kwb.pkgbuild can opt in. * Add .github/workflows/claude.yaml (responds to @claude mentions on issues and PR reviews) and claude-code-review.yaml (automatic PR review on opened/synchronize). * Ship the same files as templates under inst/templates/ci_github-actions-claude/ so they stay separate from the always-installed default workflows. * New exported use_ghactions_claude() copies just the Claude workflows into an existing package. * use_ghactions() and use_pkg() gain a claude = FALSE toggle that additionally installs the Claude workflows when TRUE. Both workflows expect a CLAUDE_CODE_OAUTH_TOKEN repo secret in GitHub. * Bump DESCRIPTION to 0.3.0 and document the workflow modernization plus the Claude Code addition in NEWS.md for the v0.3.0 release. --- .github/workflows/claude-code-review.yaml | 40 ++++++++++++++ .github/workflows/claude.yaml | 38 +++++++++++++ DESCRIPTION | 2 +- NAMESPACE | 1 + NEWS.md | 47 ++++++++++++++++ R/use_github_ci.R | 54 ++++++++++++++++--- R/use_pkg.R | 6 ++- .../claude-code-review.yaml | 40 ++++++++++++++ .../ci_github-actions-claude/claude.yaml | 38 +++++++++++++ man/use_ghactions.Rd | 15 ++++-- man/use_ghactions_claude.Rd | 16 ++++++ man/use_pkg.Rd | 5 ++ 12 files changed, 290 insertions(+), 12 deletions(-) create mode 100644 .github/workflows/claude-code-review.yaml create mode 100644 .github/workflows/claude.yaml create mode 100644 inst/templates/ci_github-actions-claude/claude-code-review.yaml create mode 100644 inst/templates/ci_github-actions-claude/claude.yaml create mode 100644 man/use_ghactions_claude.Rd diff --git a/.github/workflows/claude-code-review.yaml b/.github/workflows/claude-code-review.yaml new file mode 100644 index 0000000..10d2e3d --- /dev/null +++ b/.github/workflows/claude-code-review.yaml @@ -0,0 +1,40 @@ +name: Claude Code Review + +on: + pull_request: + types: [opened, synchronize] + +jobs: + claude-review: + runs-on: ubuntu-latest + permissions: + contents: read + pull-requests: read + issues: read + id-token: write + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + fetch-depth: 1 + + - name: Run Claude Code Review + id: claude-review + uses: anthropics/claude-code-action@v1 + with: + claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }} + prompt: | + REPO: ${{ github.repository }} + PR NUMBER: ${{ github.event.pull_request.number }} + + Please review this pull request and think hard about correctness, + edge cases, and consistency with the rest of the codebase. Use the + repository's CLAUDE.md for guidance if available. + Focus on: + - Code quality and R package best practices + - Potential bugs or logic issues + - Test coverage + - Documentation (roxygen2) completeness + - Consistency with the existing codebase + claude_args: '--model claude-opus-4-7 --allowed-tools "mcp__github_inline_comment__create_inline_comment,Bash(gh issue view:*),Bash(gh search:*),Bash(gh issue list:*),Bash(gh pr comment:*),Bash(gh pr diff:*),Bash(gh pr view:*),Bash(gh pr list:*)"' diff --git a/.github/workflows/claude.yaml b/.github/workflows/claude.yaml new file mode 100644 index 0000000..49f70bf --- /dev/null +++ b/.github/workflows/claude.yaml @@ -0,0 +1,38 @@ +name: Claude Code + +on: + issue_comment: + types: [created] + pull_request_review_comment: + types: [created] + issues: + types: [opened, assigned] + pull_request_review: + types: [submitted] + +jobs: + claude: + if: | + (github.event_name == 'issue_comment' && contains(github.event.comment.body, '@claude')) || + (github.event_name == 'pull_request_review_comment' && contains(github.event.comment.body, '@claude')) || + (github.event_name == 'pull_request_review' && contains(github.event.review.body, '@claude')) || + (github.event_name == 'issues' && (contains(github.event.issue.body, '@claude') || contains(github.event.issue.title, '@claude'))) + runs-on: ubuntu-latest + permissions: + contents: read + pull-requests: read + issues: read + id-token: write + actions: read + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + fetch-depth: 1 + + - name: Run Claude Code + id: claude + uses: anthropics/claude-code-action@v1 + with: + claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }} + claude_args: '--model claude-opus-4-7' diff --git a/DESCRIPTION b/DESCRIPTION index 02bc12b..82531ae 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,6 +1,6 @@ Package: kwb.pkgbuild Title: R package for standardised development at KWB -Version: 0.2.3 +Version: 0.3.0 Authors@R: c(person(given = "Michael", family = "Rustler", diff --git a/NAMESPACE b/NAMESPACE index f0630ef..bb41de4 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -24,6 +24,7 @@ export(use_badge_travis) export(use_codecov) export(use_description) export(use_ghactions) +export(use_ghactions_claude) export(use_gitlab_ci_blogdown) export(use_gitlab_ci_docs) export(use_gitlab_ci_ghpages) diff --git a/NEWS.md b/NEWS.md index 0bad1ce..7042e7e 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,3 +1,50 @@ +# [kwb.pkgbuild 0.3.0](https://github.com/KWB-R/kwb.pkgbuild/releases/tag/v0.3.0) 2026-05-07 + +* Modernise GitHub Actions workflows (both in `.github/workflows/` of this + repo and the templates in `inst/templates/ci_github-actions/`) so that + they run on current GitHub-hosted runners again: + + - Bump action versions: `actions/checkout@v4`, `actions/upload-artifact@v4`, + `codecov/codecov-action@v4`, and replace the deprecated `r-lib/actions@master` + references with `r-lib/actions@v2`. + + - Switch from the retired `ubuntu-20.04` runner to `ubuntu-latest` and + rename the matrix entry `oldrel` to `oldrel-1`. + + - Replace the archived `r-hub/sysreqs` step with + `r-lib/actions/setup-r-dependencies@v2`, which also handles dependency + caching out of the box. + + - Fix a stale `if: runner.os == 'Linux (no, try without!)'` condition that + silently disabled the Linux system-dependency step. + + - `pkgdown` workflow: deploy via `JamesIves/github-pages-deploy-action@v4` + on `ubuntu-latest`, with explicit `permissions: contents: write` and a + concurrency group. + + - `test-coverage` workflow: produce a Cobertura report and upload via the + new `codecov/codecov-action@v4`; upload test artefacts on failure. + + - `pr-commands` workflow: gate `/document` and `/style` jobs on + `github.event.issue.pull_request` so they no longer fire on plain issue + comments. + +* Add optional Claude Code GitHub Actions workflows (analogue to + [kwb.raindrop](https://github.com/KWB-R/kwb.raindrop/tree/main/.github/workflows)): + + - New templates in `inst/templates/ci_github-actions-claude/`: + `claude.yaml` (responds to `@claude` mentions in issues and PR reviews) + and `claude-code-review.yaml` (automatic PR review on `opened` / + `synchronize`). + + - New exported function `use_ghactions_claude()` to add only the Claude + workflows to an existing package. + + - `use_ghactions()` and `use_pkg()` gain a `claude = FALSE` toggle that + additionally installs the Claude workflows when set to `TRUE`. The + workflows expect a `CLAUDE_CODE_OAUTH_TOKEN` repository secret to be + configured in GitHub. + # [kwb.pkgbuild 0.2.3](https://github.com/KWB-R/kwb.pkgbuild/releases/tag/v0.2.3) 2022-10-24 * Fix GitHub action worfklows: diff --git a/R/use_github_ci.R b/R/use_github_ci.R index 8c65ce6..f69eca1 100644 --- a/R/use_github_ci.R +++ b/R/use_github_ci.R @@ -1,17 +1,57 @@ # use_ghactions----------------------------------------------------------------- #' Adds default .github/workflows/ -#' @return writes .github/workflows/ and adds it .Rbuildignore +#' +#' Copies the default GitHub Actions workflows (R-CMD-check, pkgdown, +#' pr-commands, test-coverage) into `.github/workflows/`. Optionally adds the +#' Claude Code workflows (`claude.yaml`, `claude-code-review.yaml`) when +#' `claude = TRUE`. Those workflows require a `CLAUDE_CODE_OAUTH_TOKEN` +#' repository secret to be configured in GitHub. +#' +#' @param claude if `TRUE`, additionally copies the Claude Code workflows +#' (`claude.yaml` and `claude-code-review.yaml`) into `.github/workflows/`. +#' Defaults to `FALSE`. +#' @return writes `.github/workflows/` and adds it to `.Rbuildignore` #' @importFrom fs dir_copy #' @export +use_ghactions <- function(claude = FALSE) +{ + fs::dir_copy( + path = system.file("templates/ci_github-actions/", package = "kwb.pkgbuild"), + new_path = ".github/workflows", + overwrite = TRUE + ) + + if (isTRUE(claude)) { + use_ghactions_claude() + } + + write_to_rbuildignore(ignore_pattern = "^\\.github$") +} + +# use_ghactions_claude---------------------------------------------------------- -use_ghactions <- function() +#' Adds Claude Code workflows to .github/workflows/ +#' +#' Copies the Claude Code workflows (`claude.yaml` and `claude-code-review.yaml`) +#' into `.github/workflows/`. Requires a `CLAUDE_CODE_OAUTH_TOKEN` repository +#' secret to be configured in GitHub for the workflows to function. +#' +#' @return writes Claude workflow YAML files into `.github/workflows/` +#' @importFrom fs dir_create file_copy dir_ls +#' @export +use_ghactions_claude <- function() { + fs::dir_create(".github/workflows") -fs::dir_copy(path = system.file("templates/ci_github-actions/", - package = "kwb.pkgbuild"), - new_path = ".github/workflows", - overwrite = TRUE) + src_dir <- system.file( + "templates/ci_github-actions-claude/", + package = "kwb.pkgbuild" + ) -write_to_rbuildignore(ignore_pattern = "^\\.github$") + fs::file_copy( + path = fs::dir_ls(src_dir, glob = "*.yaml"), + new_path = ".github/workflows/", + overwrite = TRUE + ) } diff --git a/R/use_pkg.R b/R/use_pkg.R index eff8939..7696da3 100644 --- a/R/use_pkg.R +++ b/R/use_pkg.R @@ -29,6 +29,9 @@ #' @importFrom fs dir_create #' @param auto_build_pkgdown prepare Travis for pkgdown::build_site() (default: #' FALSE), only possible if GITHUB repo already existing +#' @param claude if TRUE, additionally adds the Claude Code GitHub Actions +#' workflows (claude.yaml, claude-code-review.yaml). Requires the repository +#' secret CLAUDE_CODE_OAUTH_TOKEN to be configured in GitHub. (default: FALSE) #' @param dbg print debug messages (default: TRUE) #' @param ... additional arguments passed to use_autopkgdown() (only releveant #' if "auto_build_pkgdown" == TRUE) @@ -44,6 +47,7 @@ use_pkg <- function( domain = "github", stage = "experimental", auto_build_pkgdown = FALSE, + claude = FALSE, dbg = TRUE, ... ) @@ -63,7 +67,7 @@ use_pkg <- function( use_pkgdown(author, copyright_holder$name, pkg$name, user, domain) # Update Github Actions - use_ghactions() + use_ghactions(claude = claude) # Use codecov use_codecov() diff --git a/inst/templates/ci_github-actions-claude/claude-code-review.yaml b/inst/templates/ci_github-actions-claude/claude-code-review.yaml new file mode 100644 index 0000000..10d2e3d --- /dev/null +++ b/inst/templates/ci_github-actions-claude/claude-code-review.yaml @@ -0,0 +1,40 @@ +name: Claude Code Review + +on: + pull_request: + types: [opened, synchronize] + +jobs: + claude-review: + runs-on: ubuntu-latest + permissions: + contents: read + pull-requests: read + issues: read + id-token: write + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + fetch-depth: 1 + + - name: Run Claude Code Review + id: claude-review + uses: anthropics/claude-code-action@v1 + with: + claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }} + prompt: | + REPO: ${{ github.repository }} + PR NUMBER: ${{ github.event.pull_request.number }} + + Please review this pull request and think hard about correctness, + edge cases, and consistency with the rest of the codebase. Use the + repository's CLAUDE.md for guidance if available. + Focus on: + - Code quality and R package best practices + - Potential bugs or logic issues + - Test coverage + - Documentation (roxygen2) completeness + - Consistency with the existing codebase + claude_args: '--model claude-opus-4-7 --allowed-tools "mcp__github_inline_comment__create_inline_comment,Bash(gh issue view:*),Bash(gh search:*),Bash(gh issue list:*),Bash(gh pr comment:*),Bash(gh pr diff:*),Bash(gh pr view:*),Bash(gh pr list:*)"' diff --git a/inst/templates/ci_github-actions-claude/claude.yaml b/inst/templates/ci_github-actions-claude/claude.yaml new file mode 100644 index 0000000..49f70bf --- /dev/null +++ b/inst/templates/ci_github-actions-claude/claude.yaml @@ -0,0 +1,38 @@ +name: Claude Code + +on: + issue_comment: + types: [created] + pull_request_review_comment: + types: [created] + issues: + types: [opened, assigned] + pull_request_review: + types: [submitted] + +jobs: + claude: + if: | + (github.event_name == 'issue_comment' && contains(github.event.comment.body, '@claude')) || + (github.event_name == 'pull_request_review_comment' && contains(github.event.comment.body, '@claude')) || + (github.event_name == 'pull_request_review' && contains(github.event.review.body, '@claude')) || + (github.event_name == 'issues' && (contains(github.event.issue.body, '@claude') || contains(github.event.issue.title, '@claude'))) + runs-on: ubuntu-latest + permissions: + contents: read + pull-requests: read + issues: read + id-token: write + actions: read + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + fetch-depth: 1 + + - name: Run Claude Code + id: claude + uses: anthropics/claude-code-action@v1 + with: + claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }} + claude_args: '--model claude-opus-4-7' diff --git a/man/use_ghactions.Rd b/man/use_ghactions.Rd index c1930a8..5d047b9 100644 --- a/man/use_ghactions.Rd +++ b/man/use_ghactions.Rd @@ -4,11 +4,20 @@ \alias{use_ghactions} \title{Adds default .github/workflows/} \usage{ -use_ghactions() +use_ghactions(claude = FALSE) +} +\arguments{ +\item{claude}{if \code{TRUE}, additionally copies the Claude Code workflows +(\code{claude.yaml} and \code{claude-code-review.yaml}) into \code{.github/workflows/}. +Defaults to \code{FALSE}.} } \value{ -writes .github/workflows/ and adds it .Rbuildignore +writes \code{.github/workflows/} and adds it to \code{.Rbuildignore} } \description{ -Adds default .github/workflows/ +Copies the default GitHub Actions workflows (R-CMD-check, pkgdown, +pr-commands, test-coverage) into \code{.github/workflows/}. Optionally adds the +Claude Code workflows (\code{claude.yaml}, \code{claude-code-review.yaml}) when +\code{claude = TRUE}. Those workflows require a \code{CLAUDE_CODE_OAUTH_TOKEN} +repository secret to be configured in GitHub. } diff --git a/man/use_ghactions_claude.Rd b/man/use_ghactions_claude.Rd new file mode 100644 index 0000000..aa473c3 --- /dev/null +++ b/man/use_ghactions_claude.Rd @@ -0,0 +1,16 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/use_github_ci.R +\name{use_ghactions_claude} +\alias{use_ghactions_claude} +\title{Adds Claude Code workflows to .github/workflows/} +\usage{ +use_ghactions_claude() +} +\value{ +writes Claude workflow YAML files into \code{.github/workflows/} +} +\description{ +Copies the Claude Code workflows (\code{claude.yaml} and \code{claude-code-review.yaml}) +into \code{.github/workflows/}. Requires a \code{CLAUDE_CODE_OAUTH_TOKEN} repository +secret to be configured in GitHub for the workflows to function. +} diff --git a/man/use_pkg.Rd b/man/use_pkg.Rd index ac44d3b..467f53e 100644 --- a/man/use_pkg.Rd +++ b/man/use_pkg.Rd @@ -15,6 +15,7 @@ use_pkg( domain = "github", stage = "experimental", auto_build_pkgdown = FALSE, + claude = FALSE, dbg = TRUE, ... ) @@ -54,6 +55,10 @@ to \item{auto_build_pkgdown}{prepare Travis for pkgdown::build_site() (default: FALSE), only possible if GITHUB repo already existing} +\item{claude}{if TRUE, additionally adds the Claude Code GitHub Actions +workflows (claude.yaml, claude-code-review.yaml). Requires the repository +secret CLAUDE_CODE_OAUTH_TOKEN to be configured in GitHub. (default: FALSE)} + \item{dbg}{print debug messages (default: TRUE)} \item{...}{additional arguments passed to use_autopkgdown() (only releveant From f215646d090ec682c15f02bf0fd7d627182c547f Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 7 May 2026 06:59:35 +0000 Subject: [PATCH 13/14] Clean up R package documentation and add GitHub Actions vignette * Remove dead duplicate definitions of git(), construct_commit_message() and github_push() from R/deploy_site_github_with_extra_files.R. The duplicates were silently overwritten by later definitions in the same file but still produced misleading public Rd entries (man/github_push.Rd). * Fix incorrect @return texts (copy/paste errors) for use_index_md(), use_badge_ghactions_rcmdcheck() and use_badge_runiverse() so the man pages describe what each function actually returns. * Mark internal helpers use_installation(), read_description(), kwb_author() and kwb_package() with @noRd; remove the corresponding Rd files. NAMESPACE exports and man/ are now perfectly in sync (38=38). * Rewrite the titles / descriptions for use_pkgdown(), use_readme_md() and use_index_md(); fix typos (releveant, directoy, aleady, DESCIPTION, KWB-R" missing quote, file patern) across roxygen blocks and Rd files. * Update vignettes/tutorial.Rmd: replace stale Travis / AppVeyor references with the modern GitHub Actions workflow set, document the new claude = TRUE switch on use_pkg(), and fix the kwb.pkgdown / kwb.pkddown typos. * Add new vignette vignettes/github-actions.Rmd that explains the default workflows, the optional Claude Code integration, the required CLAUDE_CODE_OAUTH_TOKEN secret and how to refresh workflows in existing packages. * Document all of the above in NEWS.md for the v0.3.0 release. --- NEWS.md | 34 ++++++ R/deploy_site_github_with_extra_files.R | 45 +------ R/helper.R | 16 ++- R/read_description.R | 10 +- R/use_badges.R | 18 +-- R/use_gitlab_ci.R | 8 +- R/use_index_md.R | 25 ++-- R/use_installation.R | 10 +- R/use_news_md.R | 2 +- R/use_pkg.R | 2 +- R/use_pkgdown.R | 12 +- R/use_readme_md.R | 24 ++-- man/get_pkgname.Rd | 6 +- man/github_push.Rd | 12 -- man/kwb_author.Rd | 12 -- man/kwb_package.Rd | 12 -- man/read_description.Rd | 17 --- man/use_badge_appveyor.Rd | 2 +- man/use_badge_codecov.Rd | 2 +- man/use_badge_ghactions.Rd | 2 +- man/use_badge_ghactions_pkgdown.Rd | 2 +- man/use_badge_ghactions_rcmdcheck.Rd | 4 +- man/use_badge_runiverse.Rd | 4 +- man/use_badge_travis.Rd | 2 +- man/use_gitlab_ci_blogdown.Rd | 2 +- man/use_gitlab_ci_docs.Rd | 2 +- man/use_gitlab_ci_ghpages.Rd | 2 +- man/use_gitlab_ci_pkgdown.Rd | 2 +- man/use_index_md.Rd | 25 ++-- man/use_installation.Rd | 19 --- man/use_pkg.Rd | 2 +- man/use_pkgdown.Rd | 10 +- man/use_readme_md.Rd | 23 ++-- vignettes/github-actions.Rmd | 156 ++++++++++++++++++++++++ vignettes/tutorial.Rmd | 113 ++++++++++------- 35 files changed, 388 insertions(+), 251 deletions(-) delete mode 100644 man/github_push.Rd delete mode 100644 man/kwb_author.Rd delete mode 100644 man/kwb_package.Rd delete mode 100644 man/read_description.Rd delete mode 100644 man/use_installation.Rd create mode 100644 vignettes/github-actions.Rmd diff --git a/NEWS.md b/NEWS.md index 7042e7e..3336478 100644 --- a/NEWS.md +++ b/NEWS.md @@ -45,6 +45,40 @@ workflows expect a `CLAUDE_CODE_OAUTH_TOKEN` repository secret to be configured in GitHub. +* Documentation cleanup: + + - Remove dead duplicate definitions of `git()`, `construct_commit_message()` + and `github_push()` in `R/deploy_site_github_with_extra_files.R` (they + were silently overwritten by later definitions in the same file). + + - Fix copy/paste errors in `@return` for `use_index_md()`, + `use_badge_ghactions_rcmdcheck()` and `use_badge_runiverse()` (which + referenced "travis" / "codecov" badges instead of the actual return + value). + + - Mark internal helpers (`use_installation()`, `read_description()`, + `kwb_author()`, `kwb_package()`) with `@noRd` so they no longer create + public Rd entries. + + - Rewrite the titles / descriptions for `use_pkgdown()`, `use_readme_md()` + and `use_index_md()` so the man pages describe what the function + actually does. + + - Fix typos (`releveant`, `directoy`, `aleady`, `DESCIPTION`, + `(default: KWB-R")`, `file patern`) across roxygen blocks and Rd files. + +* Vignettes: + + - New vignette `vignette("github-actions", package = "kwb.pkgbuild")` + describing the default workflows, the optional Claude Code integration, + the `CLAUDE_CODE_OAUTH_TOKEN` secret, and how to refresh workflows in + existing packages. + + - Update `vignette("tutorial")`: replace stale Travis / AppVeyor + references with the GitHub Actions workflow set, document the new + `claude = TRUE` switch in `use_pkg()`, and fix the `kwb.pkgdown` / + `kwb.pkddown` typos. + # [kwb.pkgbuild 0.2.3](https://github.com/KWB-R/kwb.pkgbuild/releases/tag/v0.2.3) 2022-10-24 * Fix GitHub action worfklows: diff --git a/R/deploy_site_github_with_extra_files.R b/R/deploy_site_github_with_extra_files.R index e8fe796..9c2a639 100644 --- a/R/deploy_site_github_with_extra_files.R +++ b/R/deploy_site_github_with_extra_files.R @@ -35,26 +35,6 @@ github_url_rx <- function() { # pkgdown functions (missing in pkgdown >= 1.5.0) ------------------------------ -#' git -#' @importFrom processx run -#' @keywords internal -#' @noRd -#' -git <- function(...) { - processx::run("git", c(...), echo_cmd = TRUE, echo = TRUE) -} - -#' construct_commit_message -#' -#' @keywords internal -#' @noRd -#' -construct_commit_message <- function(pkg, commit = Sys.getenv("TRAVIS_COMMIT")) { - pkg <- pkgdown::as_pkgdown(pkg) - - sprintf("Built site for %s: %s@%s", pkg$package, pkg$version, substr(commit, 1, 7)) -} - #' rule #' @importFrom cli cat_rule #' @importFrom crayon bold @@ -83,27 +63,6 @@ github_clone <- function(dir, repo_slug) { } -#' github_push -#' -#' @importFrom withr with_dir -#' @keywords internal -#' -github_push <- function(dir, commit_message) { - # force execution before changing working directory - force(commit_message) - - rule("Commiting updated site", line = 1) - - withr::with_dir(dir, { - git("add", "-A", ".") - git("commit", "--allow-empty", "-m", commit_message) - - rule("Deploying to GitHub Pages", line = 1) - git("remote", "-v") - git("push", "--force", "origin", "HEAD:gh-pages") - }) -} - # deploy_site_github_with_extra_files ------------------------------------------ #' deploy_site_github_with_extra_files @@ -111,7 +70,7 @@ github_push <- function(dir, commit_message) { #' @description for details see pkgdown::deploy_site_github(), only parameter #' vignettes_file_pattern_to_copy added #' @param pkg "." -#' @param vignettes_file_pattern_to_copy file patern for copying files from +#' @param vignettes_file_pattern_to_copy file pattern for copying files from #' vignettes directory into deploy directory (default: "\\.json$") #' @param install Optionally, opt-out of automatic installation. This is #' necessary if the package you're documenting is a dependency of pkgdown @@ -211,7 +170,7 @@ copy_files_from_vignettes_dir_to_deploy_dir <- function( #' Assumes that you're in a git clone of the project, and the package is #' already installed. #' @param pkg "." -#' @param vignettes_file_pattern_to_copy file patern for copying files from +#' @param vignettes_file_pattern_to_copy file pattern for copying files from #' vignettes directory into deploy directory (default: "\\.json$") #' @param branch The git branch to deploy to #' @param remote The git remote to deploy to diff --git a/R/helper.R b/R/helper.R index 36907da..4b04fc9 100644 --- a/R/helper.R +++ b/R/helper.R @@ -22,9 +22,9 @@ get_from_namespace <- utils::getFromNamespace #' Helper Function: Get Package Name #' -#' @param pkgname either package name or NULL. In this -#' case the DESCRIPTION file in the current working -#' directory is read and is package name ues (default: NULL) +#' @param pkgname either package name or NULL. In the latter case the +#' DESCRIPTION file in the current working directory is read and the +#' package name from there is used (default: NULL) #' #' @return package name #' @export @@ -70,10 +70,13 @@ git_check_if_windows <- function(git_exe) # kwb_author ------------------------------------------------------------------- -#' Get Information About KWB Author +#' Get information about a KWB author #' +#' @param who key in the author registry (currently only "rustler") +#' @return list with elements `name`, `orcid`, `url` #' @importFrom kwb.utils selectElements #' @keywords internal +#' @noRd kwb_author <- function(who) { kwb.utils::selectElements(elements = who, x = list( @@ -85,10 +88,13 @@ kwb_author <- function(who) )) } -#' Get (Default) Information About KWB-R Package +#' Get (default) information about a KWB-R package #' +#' @param pkg key in the package registry (currently only "kwb.umberto") +#' @return list with elements `name`, `title`, `desc` #' @importFrom kwb.utils selectElements #' @keywords internal +#' @noRd kwb_package <- function(pkg) { kwb.utils::selectElements(elements = pkg, x = list( diff --git a/R/read_description.R b/R/read_description.R index 721a61b..670f6b0 100644 --- a/R/read_description.R +++ b/R/read_description.R @@ -1,15 +1,17 @@ # read_description ------------------------------------------------------------- -#' Helper function: read_description +#' Helper: read selected fields from a `DESCRIPTION` file #' -#' @param file path to DESCRIPTION file (default: DESCRIPTION) +#' @param file path to DESCRIPTION file (default: "DESCRIPTION") #' @importFrom desc desc -#' @return list with pkg "name", "title", "desc", "version" +#' @return list with elements `name`, `title`, `desc`, `version` +#' @keywords internal +#' @noRd read_description <- function(file = "DESCRIPTION") { if (! file.exists(file)) clean_stop( - sprintf("DESCIPTION file not found at: %s.\n", file.path(getwd(), file)), + sprintf("DESCRIPTION file not found at: %s.\n", file.path(getwd(), file)), "Please set working directory with function setwd() properly!" ) diff --git a/R/use_badges.R b/R/use_badges.R index d83ee98..be7942b 100644 --- a/R/use_badges.R +++ b/R/use_badges.R @@ -3,7 +3,7 @@ #' Badge appveyor #' @param repo name of repository (default: NULL) #' @param user user name or organisation under which repository defined in -#' parameter "repo" is hosted (default: KWB-R") +#' parameter "repo" is hosted (default: "KWB-R") #' @param domain under which repository is hosted (default: "github") #' #' @return generates appveyor badge link @@ -28,7 +28,7 @@ use_badge_appveyor <- function(repo = NULL, user = "KWB-R", domain = "github") #' Badge travis #' @param repo name of repository (default: NULL) #' @param user user name or organisation under which repository defined in -#' parameter "repo" is hosted (default: KWB-R") +#' parameter "repo" is hosted (default: "KWB-R") #' @return generates travis badge link #' @export use_badge_travis <- function(repo = NULL, user = "KWB-R") @@ -47,10 +47,10 @@ use_badge_travis <- function(repo = NULL, user = "KWB-R") #' Badge Github Actions RCMD Check #' @param repo name of repository (default: NULL) #' @param user user name or organisation under which repository defined in -#' parameter "repo" is hosted (default: KWB-R") +#' parameter "repo" is hosted (default: "KWB-R") #' @param branch default: NULL (i.e. use "default" branch) or user defined branch #' (e.g. "dev") -#' @return generates travis badge link +#' @return generates GitHub Actions R-CMD-check badge markdown #' @export use_badge_ghactions_rcmdcheck <- function(repo = NULL, user = "KWB-R", branch = NULL) @@ -70,7 +70,7 @@ use_badge_ghactions_rcmdcheck <- function(repo = NULL, user = "KWB-R", #' Badge Github Actions Pkgdown #' @param repo name of repository (default: NULL) #' @param user user name or organisation under which repository defined in -#' parameter "repo" is hosted (default: KWB-R") +#' parameter "repo" is hosted (default: "KWB-R") #' @param branch default: NULL (i.e. use "default" branch) or user defined branch #' (e.g. "dev") #' @return generates Github Actions Pkgdown badge link @@ -93,7 +93,7 @@ use_badge_ghactions_pkgdown <- function(repo = NULL, user = "KWB-R", branch = NU #' Badge Github Actions #' @param repo name of repository (default: NULL) #' @param user user name or organisation under which repository defined in -#' parameter "repo" is hosted (default: KWB-R") +#' parameter "repo" is hosted (default: "KWB-R") #' @param branch default: NULL (i.e. use "default" branch) or user defined branch #' (e.g. "dev") #' @return generates Github Actions badges link @@ -112,7 +112,7 @@ use_badge_ghactions <- function(repo = NULL, user = "KWB-R", branch = NULL) #' Badge codecov #' @param repo name of repository (default: NULL) #' @param user user name or organisation under which repository defined in -#' parameter "repo" is hosted (default: KWB-R") +#' parameter "repo" is hosted (default: "KWB-R") #' @param domain under which repository is hosted (default: "github") #' @return generates codecov badge link #' @export @@ -215,8 +215,8 @@ is_on_cran <- function(cran_link) #' Badge R-Universe #' @param repo name of repository (default: NULL) #' @param user user name or organisation under which repository defined in -#' parameter "repo" is hosted (default: KWB-R") -#' @return generates codecov badge link +#' parameter "repo" is hosted (default: "KWB-R") +#' @return generates R-Universe badge markdown #' @export use_badge_runiverse <- function(repo = NULL, user = "KWB-R") { diff --git a/R/use_gitlab_ci.R b/R/use_gitlab_ci.R index 9056728..f0feb5a 100644 --- a/R/use_gitlab_ci.R +++ b/R/use_gitlab_ci.R @@ -2,7 +2,7 @@ #' Adds .gitlab-ci.yml (if repo contains a "docs" subfolder) #' -#' @param dest_dir directoy to write (default: getwd()) +#' @param dest_dir directory to write (default: getwd()) #' @param yml_vector a yml imported as string vector (default: #' gitlab_ci_template_docs()) #' @return writes .gitlab-ci.yml and adds it .Rbuildignore @@ -26,7 +26,7 @@ use_gitlab_ci_docs <- function( # use_gitlab_ci_ghpages--------------------------------------------------------- #' Adds .gitlab-ci.yml (which should be saved in root dir of "gh-pages" branch) -#' @param dest_dir directoy to write (default: +#' @param dest_dir directory to write (default: #' getwd()) #' @param yml_vector a yml imported as string vector (default: gitlab_ci_template_ghpages()) #' @return writes .gitlab-ci.yml @@ -43,7 +43,7 @@ use_gitlab_ci_ghpages <- function( # use_gitlab_ci_blogdown-------------------------------------------------------- #' Adds .gitlab-ci.yml (if repo contains on root in a "gh-pages" branch) -#' @param dest_dir directoy to write (default: getwd()) +#' @param dest_dir directory to write (default: getwd()) #' @param yml_vector a yml imported as string vector (default: #' gitlab_ci_template_blogdown()) #' @return writes .gitlab-ci.yml @@ -61,7 +61,7 @@ use_gitlab_ci_blogdown <- function( #' Adds .gitlab-ci.yml #' -#' @param dest_dir directoy to write (default: getwd()) +#' @param dest_dir directory to write (default: getwd()) #' @param yml_vector a yml imported as string vector (default: #' gitlab_ci_template_pkgdown(), where "/" is replaced with value #' from DESCRIPTION specified in field URL, e.g. diff --git a/R/use_index_md.R b/R/use_index_md.R index ab50a5a..2b59377 100644 --- a/R/use_index_md.R +++ b/R/use_index_md.R @@ -1,14 +1,21 @@ # use_index_md ---------------------------------------------------------------- -#' Use index.md (used for pkgdown::build_home()) -#' @param user user name or organisation under which repository defined in\cr -#' parameter "repo" is hosted (default: "KWB-R")\cr -#' @param domain under which repository is hosted (default: "github") -#' @param stage badge declares the developmental stage of a package, according -#' to [https://www.tidyverse.org/lifecycle/](https://www.tidyverse.org/lifecycle/), -#' valid arguments are: "experimental", "maturing", "stable", "retired", -#' "archived", "dormant", "questioning"), (default: "experiment") -#' @return generates travis badge link +#' Create KWB-styled \code{index.md} +#' +#' Generates an \code{index.md} (used by \code{pkgdown::build_home()}) with the +#' KWB default badge set (GitHub Actions, codecov, lifecycle, CRAN, R-universe), +#' the package description from \code{DESCRIPTION} and an installation snippet. +#' @param user user name or organisation under which the repository is hosted +#' (default: "KWB-R") +#' @param domain under which the repository is hosted (default: "github") +#' @param stage badge declaring the developmental stage of the package +#' according to +#' [https://www.tidyverse.org/lifecycle/](https://www.tidyverse.org/lifecycle/); +#' valid values are "experimental", "maturing", "stable", "retired", +#' "archived", "dormant", "questioning" (default: "experimental") +#' @return writes \code{index.md} (used as `pkgdown` home) and adds the +#' pattern to \code{.Rbuildignore}. Invisibly returns the character vector +#' that was written. #' @export #' @importFrom desc desc diff --git a/R/use_installation.R b/R/use_installation.R index fbd3e56..490040f 100644 --- a/R/use_installation.R +++ b/R/use_installation.R @@ -1,11 +1,13 @@ # use_installation ------------------------------------------------------------- -#' Helper function: describe pkg installation in index.Rmd / README.md +#' Helper: describe pkg installation in index.md / README.md #' #' @param pkgname package name -#' @param user user name or organisation under which repository defined in -#' parameter "repo" is hosted -#' @param domain under which repository is hosted +#' @param user user/organisation hosting the repository +#' @param domain under which repository is hosted (e.g. "github") +#' @return character vector with markdown lines for the installation section +#' @keywords internal +#' @noRd use_installation <- function(pkgname, user, domain) { url_tutorial_install <- diff --git a/R/use_news_md.R b/R/use_news_md.R index 8dabafc..ebbdd57 100644 --- a/R/use_news_md.R +++ b/R/use_news_md.R @@ -32,7 +32,7 @@ use_news_md <- function( if (fs::file_exists(news_md)) { warning( "No 'NEWS.md' created by kwb.pkgbuild::use_news_md(),\n", - "because 'NEWS.md' is aleady existing. Please delete it first!" + "because 'NEWS.md' already exists. Please delete it first!" ) } else { writeLines(news_txt, con = "NEWS.md") diff --git a/R/use_pkg.R b/R/use_pkg.R index 7696da3..266980a 100644 --- a/R/use_pkg.R +++ b/R/use_pkg.R @@ -33,7 +33,7 @@ #' workflows (claude.yaml, claude-code-review.yaml). Requires the repository #' secret CLAUDE_CODE_OAUTH_TOKEN to be configured in GitHub. (default: FALSE) #' @param dbg print debug messages (default: TRUE) -#' @param ... additional arguments passed to use_autopkgdown() (only releveant +#' @param ... additional arguments passed to use_autopkgdown() (only relevant #' if "auto_build_pkgdown" == TRUE) #' @export use_pkg <- function( diff --git a/R/use_pkgdown.R b/R/use_pkgdown.R index 27bdae3..00898ea 100644 --- a/R/use_pkgdown.R +++ b/R/use_pkgdown.R @@ -1,14 +1,18 @@ -#' pkgdown for KWB +#' Set up `pkgdown` with KWB styling +#' +#' Calls `usethis::use_pkgdown()` and additionally writes a `_pkgdown.yml` +#' configured with KWB defaults (Bootstrap 5 + cerulean theme, KWB authors +#' block, copyright holder logo). #' #' @param author list of author attributes (default: #' kwb.pkgbuild:::kwb_author("rustler")) #' @param copyright_holder_name name of copyright holder -#' (default: kwb.pkgbuild:::kwb_string()) +#' (default: kwb.pkgbuild:::kwb_string()) #' @param pkg name of KWB package (default: get_pkgname()) #' @param user name of GitHub user/organisation (default: 'kwb-r') #' @param domain name of domain for webpage publishing (default: 'github') -#' @return performs usethis::use_pkgdown() and additionally writes _pkgdown.yml -#' based on KWB styling +#' @return invisibly; as a side effect writes `_pkgdown.yml` with KWB styling +#' and adds it to `.Rbuildignore`. #' @importFrom usethis use_pkgdown #' @importFrom kwb.utils isNaOrEmpty #' @export diff --git a/R/use_readme_md.R b/R/use_readme_md.R index d3d4f15..384cef6 100644 --- a/R/use_readme_md.R +++ b/R/use_readme_md.R @@ -1,14 +1,20 @@ # use_readme_md ---------------------------------------------------------------- -#' Use README -#' @param user user name or organisation under which repository defined in\cr -#' parameter "repo" is hosted (default: "KWB-R")\cr -#' @param domain under which repository is hosted (default: "github") -#' @param stage badge declares the developmental stage of a package, according -#' to [https://www.tidyverse.org/lifecycle/](https://www.tidyverse.org/lifecycle/), -#' valid arguments are: "experimental", "maturing", "stable", "retired", -#' "archived", "dormant", "questioning"), (default: "experiment") -#' @return generates README.md +#' Create KWB-styled `README.md` +#' +#' Generates a `README.md` with the KWB default badge set, the package +#' description from `DESCRIPTION`, an installation snippet and links to the +#' release and development documentation websites. +#' +#' @param user user name or organisation under which the repository is hosted +#' (default: "KWB-R") +#' @param domain under which the repository is hosted (default: "github") +#' @param stage badge declaring the developmental stage of the package +#' according to +#' [https://www.tidyverse.org/lifecycle/](https://www.tidyverse.org/lifecycle/); +#' valid values are "experimental", "maturing", "stable", "retired", +#' "archived", "dormant", "questioning" (default: "experimental") +#' @return writes `README.md` and adds it to `.Rbuildignore` #' @export #' @importFrom desc desc diff --git a/man/get_pkgname.Rd b/man/get_pkgname.Rd index 12f9da5..d1b5568 100644 --- a/man/get_pkgname.Rd +++ b/man/get_pkgname.Rd @@ -7,9 +7,9 @@ get_pkgname(pkgname = NULL) } \arguments{ -\item{pkgname}{either package name or NULL. In this -case the DESCRIPTION file in the current working -directory is read and is package name ues (default: NULL)} +\item{pkgname}{either package name or NULL. In the latter case the +DESCRIPTION file in the current working directory is read and the +package name from there is used (default: NULL)} } \value{ package name diff --git a/man/github_push.Rd b/man/github_push.Rd deleted file mode 100644 index f148a96..0000000 --- a/man/github_push.Rd +++ /dev/null @@ -1,12 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/deploy_site_github_with_extra_files.R -\name{github_push} -\alias{github_push} -\title{github_push} -\usage{ -github_push(dir, commit_message, remote, branch) -} -\description{ -github_push -} -\keyword{internal} diff --git a/man/kwb_author.Rd b/man/kwb_author.Rd deleted file mode 100644 index 0ae53aa..0000000 --- a/man/kwb_author.Rd +++ /dev/null @@ -1,12 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/helper.R -\name{kwb_author} -\alias{kwb_author} -\title{Get Information About KWB Author} -\usage{ -kwb_author(who) -} -\description{ -Get Information About KWB Author -} -\keyword{internal} diff --git a/man/kwb_package.Rd b/man/kwb_package.Rd deleted file mode 100644 index 9e8520c..0000000 --- a/man/kwb_package.Rd +++ /dev/null @@ -1,12 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/helper.R -\name{kwb_package} -\alias{kwb_package} -\title{Get (Default) Information About KWB-R Package} -\usage{ -kwb_package(pkg) -} -\description{ -Get (Default) Information About KWB-R Package -} -\keyword{internal} diff --git a/man/read_description.Rd b/man/read_description.Rd deleted file mode 100644 index 81a2585..0000000 --- a/man/read_description.Rd +++ /dev/null @@ -1,17 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/read_description.R -\name{read_description} -\alias{read_description} -\title{Helper function: read_description} -\usage{ -read_description(file = "DESCRIPTION") -} -\arguments{ -\item{file}{path to DESCRIPTION file (default: DESCRIPTION)} -} -\value{ -list with pkg "name", "title", "desc", "version" -} -\description{ -Helper function: read_description -} diff --git a/man/use_badge_appveyor.Rd b/man/use_badge_appveyor.Rd index 0aebcf9..ada8c9d 100644 --- a/man/use_badge_appveyor.Rd +++ b/man/use_badge_appveyor.Rd @@ -10,7 +10,7 @@ use_badge_appveyor(repo = NULL, user = "KWB-R", domain = "github") \item{repo}{name of repository (default: NULL)} \item{user}{user name or organisation under which repository defined in -parameter "repo" is hosted (default: KWB-R")} +parameter "repo" is hosted (default: "KWB-R")} \item{domain}{under which repository is hosted (default: "github")} } diff --git a/man/use_badge_codecov.Rd b/man/use_badge_codecov.Rd index 9a24ff8..03123f7 100644 --- a/man/use_badge_codecov.Rd +++ b/man/use_badge_codecov.Rd @@ -10,7 +10,7 @@ use_badge_codecov(repo = NULL, user = "KWB-R", domain = "github") \item{repo}{name of repository (default: NULL)} \item{user}{user name or organisation under which repository defined in -parameter "repo" is hosted (default: KWB-R")} +parameter "repo" is hosted (default: "KWB-R")} \item{domain}{under which repository is hosted (default: "github")} } diff --git a/man/use_badge_ghactions.Rd b/man/use_badge_ghactions.Rd index 52e5d21..364d76d 100644 --- a/man/use_badge_ghactions.Rd +++ b/man/use_badge_ghactions.Rd @@ -10,7 +10,7 @@ use_badge_ghactions(repo = NULL, user = "KWB-R", branch = NULL) \item{repo}{name of repository (default: NULL)} \item{user}{user name or organisation under which repository defined in -parameter "repo" is hosted (default: KWB-R")} +parameter "repo" is hosted (default: "KWB-R")} \item{branch}{default: NULL (i.e. use "default" branch) or user defined branch (e.g. "dev")} diff --git a/man/use_badge_ghactions_pkgdown.Rd b/man/use_badge_ghactions_pkgdown.Rd index 9cce992..a6b8146 100644 --- a/man/use_badge_ghactions_pkgdown.Rd +++ b/man/use_badge_ghactions_pkgdown.Rd @@ -10,7 +10,7 @@ use_badge_ghactions_pkgdown(repo = NULL, user = "KWB-R", branch = NULL) \item{repo}{name of repository (default: NULL)} \item{user}{user name or organisation under which repository defined in -parameter "repo" is hosted (default: KWB-R")} +parameter "repo" is hosted (default: "KWB-R")} \item{branch}{default: NULL (i.e. use "default" branch) or user defined branch (e.g. "dev")} diff --git a/man/use_badge_ghactions_rcmdcheck.Rd b/man/use_badge_ghactions_rcmdcheck.Rd index 1213649..e845a37 100644 --- a/man/use_badge_ghactions_rcmdcheck.Rd +++ b/man/use_badge_ghactions_rcmdcheck.Rd @@ -10,13 +10,13 @@ use_badge_ghactions_rcmdcheck(repo = NULL, user = "KWB-R", branch = NULL) \item{repo}{name of repository (default: NULL)} \item{user}{user name or organisation under which repository defined in -parameter "repo" is hosted (default: KWB-R")} +parameter "repo" is hosted (default: "KWB-R")} \item{branch}{default: NULL (i.e. use "default" branch) or user defined branch (e.g. "dev")} } \value{ -generates travis badge link +generates GitHub Actions R-CMD-check badge markdown } \description{ Badge Github Actions RCMD Check diff --git a/man/use_badge_runiverse.Rd b/man/use_badge_runiverse.Rd index 7c2b382..d8bae9f 100644 --- a/man/use_badge_runiverse.Rd +++ b/man/use_badge_runiverse.Rd @@ -10,10 +10,10 @@ use_badge_runiverse(repo = NULL, user = "KWB-R") \item{repo}{name of repository (default: NULL)} \item{user}{user name or organisation under which repository defined in -parameter "repo" is hosted (default: KWB-R")} +parameter "repo" is hosted (default: "KWB-R")} } \value{ -generates codecov badge link +generates R-Universe badge markdown } \description{ Badge R-Universe diff --git a/man/use_badge_travis.Rd b/man/use_badge_travis.Rd index 15b7843..e68027d 100644 --- a/man/use_badge_travis.Rd +++ b/man/use_badge_travis.Rd @@ -10,7 +10,7 @@ use_badge_travis(repo = NULL, user = "KWB-R") \item{repo}{name of repository (default: NULL)} \item{user}{user name or organisation under which repository defined in -parameter "repo" is hosted (default: KWB-R")} +parameter "repo" is hosted (default: "KWB-R")} } \value{ generates travis badge link diff --git a/man/use_gitlab_ci_blogdown.Rd b/man/use_gitlab_ci_blogdown.Rd index 086d596..76145ee 100644 --- a/man/use_gitlab_ci_blogdown.Rd +++ b/man/use_gitlab_ci_blogdown.Rd @@ -10,7 +10,7 @@ use_gitlab_ci_blogdown( ) } \arguments{ -\item{dest_dir}{directoy to write (default: getwd())} +\item{dest_dir}{directory to write (default: getwd())} \item{yml_vector}{a yml imported as string vector (default: gitlab_ci_template_blogdown())} diff --git a/man/use_gitlab_ci_docs.Rd b/man/use_gitlab_ci_docs.Rd index 79deacc..8a577d3 100644 --- a/man/use_gitlab_ci_docs.Rd +++ b/man/use_gitlab_ci_docs.Rd @@ -7,7 +7,7 @@ use_gitlab_ci_docs(dest_dir = getwd(), yml_vector = gitlab_ci_template_docs()) } \arguments{ -\item{dest_dir}{directoy to write (default: getwd())} +\item{dest_dir}{directory to write (default: getwd())} \item{yml_vector}{a yml imported as string vector (default: gitlab_ci_template_docs())} diff --git a/man/use_gitlab_ci_ghpages.Rd b/man/use_gitlab_ci_ghpages.Rd index 94d90c1..e453184 100644 --- a/man/use_gitlab_ci_ghpages.Rd +++ b/man/use_gitlab_ci_ghpages.Rd @@ -10,7 +10,7 @@ use_gitlab_ci_ghpages( ) } \arguments{ -\item{dest_dir}{directoy to write (default: +\item{dest_dir}{directory to write (default: getwd())} \item{yml_vector}{a yml imported as string vector (default: gitlab_ci_template_ghpages())} diff --git a/man/use_gitlab_ci_pkgdown.Rd b/man/use_gitlab_ci_pkgdown.Rd index 02c7ba9..08db798 100644 --- a/man/use_gitlab_ci_pkgdown.Rd +++ b/man/use_gitlab_ci_pkgdown.Rd @@ -10,7 +10,7 @@ use_gitlab_ci_pkgdown( ) } \arguments{ -\item{dest_dir}{directoy to write (default: getwd())} +\item{dest_dir}{directory to write (default: getwd())} \item{yml_vector}{a yml imported as string vector (default: gitlab_ci_template_pkgdown(), where "/" is replaced with value diff --git a/man/use_index_md.Rd b/man/use_index_md.Rd index 082a3da..43246a3 100644 --- a/man/use_index_md.Rd +++ b/man/use_index_md.Rd @@ -2,24 +2,29 @@ % Please edit documentation in R/use_index_md.R \name{use_index_md} \alias{use_index_md} -\title{Use index.md (used for pkgdown::build_home())} +\title{Create KWB-styled \code{index.md}} \usage{ use_index_md(user = "KWB-R", domain = "github", stage = "experimental") } \arguments{ -\item{user}{user name or organisation under which repository defined in\cr -parameter "repo" is hosted (default: "KWB-R")\cr} +\item{user}{user name or organisation under which the repository is hosted +(default: "KWB-R")} -\item{domain}{under which repository is hosted (default: "github")} +\item{domain}{under which the repository is hosted (default: "github")} -\item{stage}{badge declares the developmental stage of a package, according -to [https://www.tidyverse.org/lifecycle/](https://www.tidyverse.org/lifecycle/), -valid arguments are: "experimental", "maturing", "stable", "retired", -"archived", "dormant", "questioning"), (default: "experiment")} +\item{stage}{badge declaring the developmental stage of the package +according to +\url{https://www.tidyverse.org/lifecycle/}; +valid values are "experimental", "maturing", "stable", "retired", +"archived", "dormant", "questioning" (default: "experimental")} } \value{ -generates travis badge link +writes \code{index.md} (used as \code{pkgdown} home) and adds the +pattern to \code{.Rbuildignore}. Invisibly returns the character vector +that was written. } \description{ -Use index.md (used for pkgdown::build_home()) +Generates an \code{index.md} (used by \code{pkgdown::build_home()}) with the +KWB default badge set (GitHub Actions, codecov, lifecycle, CRAN, R-universe), +the package description from \code{DESCRIPTION} and an installation snippet. } diff --git a/man/use_installation.Rd b/man/use_installation.Rd deleted file mode 100644 index f797ba0..0000000 --- a/man/use_installation.Rd +++ /dev/null @@ -1,19 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/use_installation.R -\name{use_installation} -\alias{use_installation} -\title{Helper function: describe pkg installation in index.Rmd / README.md} -\usage{ -use_installation(pkgname, user, domain) -} -\arguments{ -\item{pkgname}{package name} - -\item{user}{user name or organisation under which repository defined in -parameter "repo" is hosted} - -\item{domain}{under which repository is hosted} -} -\description{ -Helper function: describe pkg installation in index.Rmd / README.md -} diff --git a/man/use_pkg.Rd b/man/use_pkg.Rd index 467f53e..263259d 100644 --- a/man/use_pkg.Rd +++ b/man/use_pkg.Rd @@ -61,7 +61,7 @@ secret CLAUDE_CODE_OAUTH_TOKEN to be configured in GitHub. (default: FALSE)} \item{dbg}{print debug messages (default: TRUE)} -\item{...}{additional arguments passed to use_autopkgdown() (only releveant +\item{...}{additional arguments passed to use_autopkgdown() (only relevant if "auto_build_pkgdown" == TRUE)} } \value{ diff --git a/man/use_pkgdown.Rd b/man/use_pkgdown.Rd index 9ab4c1b..6709f19 100644 --- a/man/use_pkgdown.Rd +++ b/man/use_pkgdown.Rd @@ -2,7 +2,7 @@ % Please edit documentation in R/use_pkgdown.R \name{use_pkgdown} \alias{use_pkgdown} -\title{pkgdown for KWB} +\title{Set up \code{pkgdown} with KWB styling} \usage{ use_pkgdown( author = kwb_author("rustler"), @@ -26,9 +26,11 @@ kwb.pkgbuild:::kwb_author("rustler"))} \item{domain}{name of domain for webpage publishing (default: 'github')} } \value{ -performs usethis::use_pkgdown() and additionally writes _pkgdown.yml -based on KWB styling +invisibly; as a side effect writes \code{_pkgdown.yml} with KWB styling +and adds it to \code{.Rbuildignore}. } \description{ -pkgdown for KWB +Calls \code{usethis::use_pkgdown()} and additionally writes a \code{_pkgdown.yml} +configured with KWB defaults (Bootstrap 5 + cerulean theme, KWB authors +block, copyright holder logo). } diff --git a/man/use_readme_md.Rd b/man/use_readme_md.Rd index ee56a7a..a1aca0e 100644 --- a/man/use_readme_md.Rd +++ b/man/use_readme_md.Rd @@ -2,24 +2,27 @@ % Please edit documentation in R/use_readme_md.R \name{use_readme_md} \alias{use_readme_md} -\title{Use README} +\title{Create KWB-styled \code{README.md}} \usage{ use_readme_md(user = "KWB-R", domain = "github", stage = "experimental") } \arguments{ -\item{user}{user name or organisation under which repository defined in\cr -parameter "repo" is hosted (default: "KWB-R")\cr} +\item{user}{user name or organisation under which the repository is hosted +(default: "KWB-R")} -\item{domain}{under which repository is hosted (default: "github")} +\item{domain}{under which the repository is hosted (default: "github")} -\item{stage}{badge declares the developmental stage of a package, according -to [https://www.tidyverse.org/lifecycle/](https://www.tidyverse.org/lifecycle/), -valid arguments are: "experimental", "maturing", "stable", "retired", -"archived", "dormant", "questioning"), (default: "experiment")} +\item{stage}{badge declaring the developmental stage of the package +according to +\url{https://www.tidyverse.org/lifecycle/}; +valid values are "experimental", "maturing", "stable", "retired", +"archived", "dormant", "questioning" (default: "experimental")} } \value{ -generates README.md +writes \code{README.md} and adds it to \code{.Rbuildignore} } \description{ -Use README +Generates a \code{README.md} with the KWB default badge set, the package +description from \code{DESCRIPTION}, an installation snippet and links to the +release and development documentation websites. } diff --git a/vignettes/github-actions.Rmd b/vignettes/github-actions.Rmd new file mode 100644 index 0000000..f5e34db --- /dev/null +++ b/vignettes/github-actions.Rmd @@ -0,0 +1,156 @@ +--- +title: "GitHub Actions for KWB-R Packages" +author: "Michael Rustler, Hauke Sonnenberg" +date: "`r Sys.Date()`" +output: rmarkdown::html_vignette +vignette: > + %\VignetteIndexEntry{GitHub Actions for KWB-R Packages} + %\VignetteEngine{knitr::rmarkdown} + %\VignetteEncoding{UTF-8} +--- + +```{r setup, include = FALSE} +knitr::opts_chunk$set( + collapse = TRUE, + fig_caption = FALSE, + comment = "#>", + eval = FALSE +) +``` + +`kwb.pkgbuild` ships a curated set of [GitHub +Actions](https://github.com/features/actions) workflows that we use across +all KWB-R packages. The workflows live as templates in +`inst/templates/ci_github-actions/` (default workflows) and +`inst/templates/ci_github-actions-claude/` (optional Claude Code +integration), and are installed into a package's `.github/workflows/` +directory by `use_ghactions()` / `use_pkg()`. + +This vignette explains what the workflows do, how to add or update them, and +how to enable the optional Claude Code integration. + +# 1 Default workflows + +`kwb.pkgbuild::use_ghactions()` (also called from `kwb.pkgbuild::use_pkg()`) +copies four workflows into `.github/workflows/`: + +| File | Purpose | +|:----------------------|:---------------------------------------------------------------------------------------------------------| +| `R-CMD-check.yaml` | Cross-platform `R CMD check` matrix (macOS, Ubuntu, Windows × `release`, `devel`, `oldrel-1`). | +| `pkgdown.yaml` | Builds the `pkgdown` site and deploys it to the `gh-pages` branch on push to `main`/`master`/`dev`. | +| `test-coverage.yaml` | Runs `covr::package_coverage()` and uploads the report to [codecov.io](https://codecov.io). | +| `pr-commands.yaml` | Reacts to `/document` and `/style` comments on pull requests by running `roxygen2` / `styler` for you. | + +All four use the official [`r-lib/actions`](https://github.com/r-lib/actions) +v2 building blocks, which means dependency installation and caching are +handled by `r-lib/actions/setup-r-dependencies@v2`. + +To install or refresh the default workflows in a package, run: + +```{r} +# from the package root +kwb.pkgbuild::use_ghactions() +``` + +# 2 Optional: Claude Code workflows + +If you want [Claude Code](https://docs.claude.com/en/docs/claude-code/) to +review your pull requests and answer `@claude` mentions in issues / PR +comments, set `claude = TRUE` when bootstrapping a new package: + +```{r} +kwb.pkgbuild::use_pkg( + author = author, + pkg = description, + version = "0.0.0.9000", + stage = "experimental", + claude = TRUE +) +``` + +Or add the workflows to an existing package after the fact: + +```{r} +kwb.pkgbuild::use_ghactions_claude() +``` + +This installs two additional workflow files: + +| File | Trigger | +|:---------------------------|:------------------------------------------------------------------------------------------------------------| +| `claude.yaml` | `issue_comment`, `pull_request_review_comment`, `pull_request_review`, `issues` — reacts to `@claude` mentions. | +| `claude-code-review.yaml` | `pull_request` (`opened`, `synchronize`) — automatic PR review. | + +## 2.1 Required repository secret + +Both workflows authenticate via a GitHub Actions secret named +`CLAUDE_CODE_OAUTH_TOKEN`. To create it: + +1. Open the repository on GitHub and go to + **Settings → Secrets and variables → Actions → New repository secret**. +2. Set **Name** to `CLAUDE_CODE_OAUTH_TOKEN` and paste your Claude Code OAuth + token as **Value**. + +Without this secret the Claude jobs will fail at the +`anthropics/claude-code-action@v1` step. + +## 2.2 What Claude does + +`claude.yaml` runs whenever someone mentions `@claude` in an issue body / +title, an issue comment, a PR review or a PR review comment. Claude then +opens a session with read access to issues / pull requests, plans, and +posts a reply. + +`claude-code-review.yaml` runs on every newly opened or updated pull +request. It reviews the diff with focus on: + +- code quality and R package best practices, +- potential bugs or logic issues, +- test coverage, +- `roxygen2` documentation completeness, +- consistency with the existing codebase. + +If your repository contains a `CLAUDE.md` file, Claude will use it as +project-specific guidance. + +# 3 Updating workflows in existing packages + +The workflows in `inst/templates/ci_github-actions/` are the source of truth +for KWB-R packages. When upstream actions are updated (e.g. a new version of +`r-lib/actions`) we bump the templates here in `kwb.pkgbuild` and re-run +`kwb.pkgbuild::use_ghactions()` in each package to refresh the local +workflows. + +To check whether a package is using an outdated version, simply diff its +`.github/workflows/` against the templates in the latest installed +`kwb.pkgbuild`: + +```{r} +template_dir <- system.file( + "templates/ci_github-actions", + package = "kwb.pkgbuild" +) + +# from the package root +list.files(".github/workflows", full.names = TRUE) +list.files(template_dir, full.names = TRUE) +``` + +# 4 Troubleshooting + +- **The pkgdown workflow doesn't deploy.** Make sure the `gh-pages` branch + exists and that **Settings → Pages → Source** points to it. The first + time a package is set up, run `kwb.pkgbuild::use_autopkgdown()` to create + the orphan branch. + +- **`R CMD check` fails on `oldrel-1`.** Either pin a `Depends: R (>= ...)` + in `DESCRIPTION` to the lowest R version you actually want to support, or + remove `oldrel-1` from the matrix in `R-CMD-check.yaml`. + +- **Claude jobs are skipped.** The `if:` clause requires `@claude` to appear + in the comment / review / issue body. The Claude review workflow only + runs on `pull_request`, not on `issue_comment` events. + +- **Codecov upload fails on forks.** Configure the `CODECOV_TOKEN` + repository secret. The workflow has `fail_ci_if_error` set conditionally + so PRs from forks won't break the build. diff --git a/vignettes/tutorial.Rmd b/vignettes/tutorial.Rmd index 076f94a..6fcf321 100644 --- a/vignettes/tutorial.Rmd +++ b/vignettes/tutorial.Rmd @@ -36,11 +36,11 @@ building and testing of the package. # 1 Install required R packages -Before you can use the package kwb.pkgdown you need to +Before you can use the package `kwb.pkgbuild` you need to -* install packages that kwb.pkgdown relies on from the -[Comprehensive R Archive Network (CRAN)](https://cloud.r-project.org), -* install kwb.pkddown from [GitHub](https://github.com). +* install the packages that `kwb.pkgbuild` relies on from the + [Comprehensive R Archive Network (CRAN)](https://cloud.r-project.org), +* install `kwb.pkgbuild` from [GitHub](https://github.com). Install required packages that are not yet available in your local R user library from CRAN: @@ -204,50 +204,73 @@ description <- list( ) ``` -## 2.4 Create R package structure in KWB-R style +## 2.4 Create R package structure in KWB-R style -Running the following code not only creates an R package structure but also adds -some KWB-R specfic styling, e.g.: +Running the following code not only creates an R package structure but also +adds some KWB-R specific styling, e.g.: -- Adding configution files for: - - + Continous integration on windows (https://appveyor.com) and linux - (https://travis-ci.org/KWB-R) - - + Code coverage in R package using the servive [codecov.io](codecov.io) - - + Backup of Github repositories on our mirrored KWB-R group on - [Gitlab](https://gitlab.com/KWB-R) +- Configuration files for: + + + Continuous integration via + [GitHub Actions](https://github.com/features/actions): the workflows + `R-CMD-check`, `pkgdown`, `pr-commands` and `test-coverage` are written + to `.github/workflows/` (see also the GitHub Actions vignette + `vignette("github-actions", package = "kwb.pkgbuild")`). + + + Code coverage via [codecov.io](https://codecov.io) + + + Backup of GitHub repositories on our mirrored KWB-R group on + [GitLab](https://gitlab.com/KWB-R) - Indicates the current lifecycle of the R package according to -https://www.tidyverse.org/lifecycle/ + https://www.tidyverse.org/lifecycle/ - Uses by default the permissive -[![MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) -for all public R packages currently hosted on Github (see: -http://kwb-r.github.io/status/) and lists KWB as copyright holder (see e.g. -[here](https://kwb-r.github.io/kwb.pkgbuild/authors.html)) + [![MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) + for all public R packages currently hosted on GitHub (see: + https://kwb-r.github.io/status/) and lists KWB as copyright holder (see e.g. + [here](https://kwb-r.github.io/kwb.pkgbuild/authors.html)) -- Creates `README` files (`README.Rmd` and `README.md`) for the above mentioned -topics and +- Creates `README.md` and `index.md` files for the above mentioned topics, and -- Prepares a KWB-R flavored documentation website template named -`_packagedown.yml` needed by http://pkgdown.r-lib.org/ +- Prepares a KWB-R flavoured documentation website template named + `_pkgdown.yml` (Bootstrap 5, KWB authors block) needed by + https://pkgdown.r-lib.org/ -Running the following R function will create the R package with the `version` = -`0.0.0.9000` and development stage `experimental` (defined [here](https://www.tidyverse.org/lifecycle/#experimental)). +Running the following R function will create the R package with `version = +"0.0.0.9000"` and development stage `experimental` (defined +[here](https://www.tidyverse.org/lifecycle/#experimental)). ```{r eval = FALSE} setwd(pkg_dir) kwb.pkgbuild::use_pkg( - author, - description, - version = "0.0.0.9000", + author, + description, + version = "0.0.0.9000", stage = "experimental" ) ``` +If you also want the [Claude Code](https://docs.claude.com/en/docs/claude-code/) +GitHub Actions workflows (for `@claude` mentions in issues / PR review +comments and automatic PR review on `opened` / `synchronize`), set +`claude = TRUE`: + +```{r eval = FALSE} +kwb.pkgbuild::use_pkg( + author, + description, + version = "0.0.0.9000", + stage = "experimental", + claude = TRUE +) +``` + +The two extra workflows expect a `CLAUDE_CODE_OAUTH_TOKEN` repository secret +to be configured in GitHub. You can also add the Claude workflows to an +existing package later on with `kwb.pkgbuild::use_ghactions_claude()`. + ## 2.5 Add your R functions Add your R functions in the folder `R`/. By using `usethis::use_r` with the @@ -384,28 +407,28 @@ knitr::include_graphics("images/package_documentation.jpg") ## 5.2 Automatically -In case you have already a Github repo defined for your R package you can -also automate the process of updating the `pkgdown::build_site()` by with the -wrapper function `kwb.pkgbuild::use_autopkgdown()`, which: - -- creates a new branch "gh-pages" where the documentation site is deployed +If you already have a GitHub repository for your R package you can let the +`pkgdown` workflow build and deploy the documentation site for you on every +push. `kwb.pkgbuild::use_pkg()` already installs the workflow +`.github/workflows/pkgdown.yaml`; the only one-off step that is left to do +is creating the `gh-pages` branch and setting it as the GitHub Pages source. -- sets "docs" folder to ".gitignore" (as these files are now build on Travis) +The wrapper function `kwb.pkgbuild::use_autopkgdown()` does exactly that: -- prepares Github Actions by: +- adds the `docs/` folder to `.gitignore` (since the site is built on + GitHub Actions and pushed to the `gh-pages` branch), - + creating ".github/workflows/" with `kwb.pkgbuild::use_ghactions()` - - + creating an empty "gh-pages" branch with - `kwb.pkgbuild::create_empty_branch_ghpages()` +- creates an empty `gh-pages` branch via + `kwb.pkgbuild::create_empty_branch_ghpages()`. ```{r eval = FALSE} kwb.pkgbuild::use_autopkgdown() ``` -Finally to need to go to: +Finally, go to -https://github.com/KWB-R/ `kwb.mycoolrpackage` /settings +`https://github.com/KWB-R//settings/pages` -and set the "source" for Github Pages to the branch "gh-pages". After each -successful Travis build the documentation website is now also updated! +and set the GitHub Pages **Source** to the branch `gh-pages`. After every +successful run of the `pkgdown` workflow the documentation website is now +updated automatically. From 0e967ce7e4ad217e310f6f8919c50e46c13e951e Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 7 May 2026 07:09:07 +0000 Subject: [PATCH 14/14] Expose KWB logo URL as default parameter in use_pkgdown() The KWB logo URL https://logos.kompetenz-wasser.io/KWB_Logo_M_Blau_RGB.svg was previously hardcoded inside the body of use_pkgdown(). Lift it to two new parameters kwb_logo_url and kwb_logo_href with that URL (and https://www.kompetenz-wasser.de) as defaults, so the default logo is explicit, discoverable in the man page, and can be overridden per package without copy-pasting the function. Also bumps the href default from http:// to https://. --- NEWS.md | 6 ++++++ R/use_pkgdown.R | 18 +++++++++++++----- man/use_pkgdown.Rd | 11 ++++++++++- 3 files changed, 29 insertions(+), 6 deletions(-) diff --git a/NEWS.md b/NEWS.md index 3336478..52fa618 100644 --- a/NEWS.md +++ b/NEWS.md @@ -67,6 +67,12 @@ - Fix typos (`releveant`, `directoy`, `aleady`, `DESCIPTION`, `(default: KWB-R")`, `file patern`) across roxygen blocks and Rd files. +* `use_pkgdown()`: expose the KWB logo as parameters `kwb_logo_url` + (default: `https://logos.kompetenz-wasser.io/KWB_Logo_M_Blau_RGB.svg`) + and `kwb_logo_href` (default: `https://www.kompetenz-wasser.de`) so the + default logo URL is no longer hardcoded inside the function body and can + be overridden per package without forking the function. + * Vignettes: - New vignette `vignette("github-actions", package = "kwb.pkgbuild")` diff --git a/R/use_pkgdown.R b/R/use_pkgdown.R index 00898ea..dd2341d 100644 --- a/R/use_pkgdown.R +++ b/R/use_pkgdown.R @@ -11,6 +11,11 @@ #' @param pkg name of KWB package (default: get_pkgname()) #' @param user name of GitHub user/organisation (default: 'kwb-r') #' @param domain name of domain for webpage publishing (default: 'github') +#' @param kwb_logo_url URL of the KWB logo image embedded in the copyright +#' holder's `pkgdown` author block (default: +#' `"https://logos.kompetenz-wasser.io/KWB_Logo_M_Blau_RGB.svg"`) +#' @param kwb_logo_href URL the KWB logo links to (default: +#' `"https://www.kompetenz-wasser.de"`) #' @return invisibly; as a side effect writes `_pkgdown.yml` with KWB styling #' and adds it to `.Rbuildignore`. #' @importFrom usethis use_pkgdown @@ -21,7 +26,9 @@ use_pkgdown <- function( copyright_holder_name = kwb_string(), pkg = get_pkgname(), user = "kwb-r", - domain = "github" + domain = "github", + kwb_logo_url = "https://logos.kompetenz-wasser.io/KWB_Logo_M_Blau_RGB.svg", + kwb_logo_href = "https://www.kompetenz-wasser.de" ) { usethis::use_pkgdown() @@ -40,10 +47,11 @@ use_pkgdown <- function( if (copyright_holder_name == kwb_string()) { authors <- c(authors, stats::setNames(nm = copyright_holder_name, list(list( - href = "http://www.kompetenz-wasser.de", - html = paste0( - "KWB") + href = kwb_logo_href, + html = sprintf( + "KWB", + kwb_logo_url + ) )))) } diff --git a/man/use_pkgdown.Rd b/man/use_pkgdown.Rd index 6709f19..4f8981b 100644 --- a/man/use_pkgdown.Rd +++ b/man/use_pkgdown.Rd @@ -9,7 +9,9 @@ use_pkgdown( copyright_holder_name = kwb_string(), pkg = get_pkgname(), user = "kwb-r", - domain = "github" + domain = "github", + kwb_logo_url = "https://logos.kompetenz-wasser.io/KWB_Logo_M_Blau_RGB.svg", + kwb_logo_href = "https://www.kompetenz-wasser.de" ) } \arguments{ @@ -24,6 +26,13 @@ kwb.pkgbuild:::kwb_author("rustler"))} \item{user}{name of GitHub user/organisation (default: 'kwb-r')} \item{domain}{name of domain for webpage publishing (default: 'github')} + +\item{kwb_logo_url}{URL of the KWB logo image embedded in the copyright +holder's \code{pkgdown} author block (default: +\code{"https://logos.kompetenz-wasser.io/KWB_Logo_M_Blau_RGB.svg"})} + +\item{kwb_logo_href}{URL the KWB logo links to (default: +\code{"https://www.kompetenz-wasser.de"})} } \value{ invisibly; as a side effect writes \code{_pkgdown.yml} with KWB styling