├── .Rbuildignore ├── .gitattributes ├── .github ├── CONTRIBUTING.md ├── issue_template.md ├── pull_request_template.md └── workflows │ └── R-CMD-check.yaml ├── .gitignore ├── CODE_OF_CONDUCT.md ├── DESCRIPTION ├── LICENSE ├── Makefile ├── NAMESPACE ├── R ├── cch_heartbeat.R ├── cch_history.R ├── cch_maintainers.R ├── cch_pkgs.R ├── cch_pkgs_history.R ├── cch_pkgs_search.R ├── cchecks-package.R ├── cchn_register.R ├── cchn_rules.R ├── email-utils.R ├── http.R ├── rule-add.R ├── rule-delete.R ├── rule-get.R ├── rule-list.R └── zzz.R ├── README-not.md ├── README.Rmd ├── README.md ├── cchecks.Rproj ├── man ├── cch_heartbeat.Rd ├── cch_history.Rd ├── cch_maintainers.Rd ├── cch_pkgs.Rd ├── cch_pkgs_history.Rd ├── cch_pkgs_search.Rd ├── cchecks-package.Rd ├── cchn_register.Rd └── cchn_rules.Rd ├── tests ├── fixtures │ ├── cch_heartbeat.yml │ ├── cch_history_error.yml │ ├── cch_maintainers_all_maints.yml │ ├── cch_maintainers_error.yml │ ├── cch_maintainers_one_maint.yml │ ├── cch_pkgs_all_pkgs.yml │ ├── cch_pkgs_error.yml │ ├── cch_pkgs_history_error.yml │ ├── cch_pkgs_history_one_pkg.yml │ ├── cch_pkgs_one_pkg.yml │ ├── cch_pkgs_search.yml │ ├── cch_pkgs_search_error.yml │ ├── cch_pkgs_search_limit_by_package.yml │ ├── cchn_pkg_rule_add.yml │ ├── cchn_pkg_rule_add_cleanup.yml │ ├── cchn_pkg_rule_get_add_rule.yml │ ├── cchn_pkg_rule_get_cleanup.yml │ ├── cchn_pkg_rule_get_not_found.yml │ ├── cchn_pkg_rule_get_one_rule.yml │ ├── cchn_pkg_rule_list_add_rule.yml │ ├── cchn_pkg_rule_list_cleanup.yml │ ├── cchn_pkg_rule_list_empty.yml │ ├── cchn_pkg_rule_list_one_rule.yml │ ├── cchn_rule_add.yml │ ├── cchn_rule_add_cleanup.yml │ ├── cchn_rule_get_add_rule.yml │ ├── cchn_rule_get_cleanup.yml │ ├── cchn_rule_get_empty_rule_list.yml │ ├── cchn_rule_get_not_found.yml │ ├── cchn_rule_get_one_rule.yml │ ├── cchn_rule_list_add_rule.yml │ ├── cchn_rule_list_cleanup.yml │ ├── cchn_rule_list_empty.yml │ ├── cchn_rule_list_one_rule.yml │ ├── cchn_rules_add.yml │ └── cchn_rules_add_cleanup.yml ├── testthat.R └── testthat │ ├── helper-cchecks.R │ ├── test-cch_heartbeat.R │ ├── test-cch_history.R │ ├── test-cch_maintainers.R │ ├── test-cch_pkgs.R │ ├── test-cch_pkgs_history.R │ ├── test-cch_pkgs_search.R │ ├── test-cchn_pkg_rule_add.R │ ├── test-cchn_pkg_rule_get.R │ ├── test-cchn_pkg_rule_list.R │ ├── test-cchn_rule_add.R │ ├── test-cchn_rule_get.R │ ├── test-cchn_rule_list.R │ └── test-cchn_rules_add.R └── vignettes ├── cchecks.Rmd └── cchecks.Rmd.og /.Rbuildignore: -------------------------------------------------------------------------------- 1 | ^.*\.Rproj$ 2 | ^\.Rproj\.user$ 3 | ^CODE_OF_CONDUCT\.md$ 4 | README.Rmd 5 | .travis.yml 6 | appveyor.yml 7 | man-roxygen 8 | ^cran-comments\.md$ 9 | .github 10 | ^Makefile$ 11 | scotts_rules.R 12 | rules_egs.R 13 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto 2 | tests/fixtures/**/* -diff 3 | -------------------------------------------------------------------------------- /.github/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # CONTRIBUTING # 2 | 3 | ### Bugs? 4 | 5 | * Submit an issue on the [Issues page](https://github.com/ropensci/cchecks/issues) 6 | 7 | ### Code contributions 8 | 9 | * Fork this repo to your Github account 10 | * Clone your version on your account down to your machine from your account, e.g,. `git clone https://github.com//cchecks.git` 11 | * Make sure to track progress upstream (i.e., on our version of `cchecks` at `ropensci/cchecks`) by doing `git remote add upstream https://github.com/ropensci/cchecks.git`. Before making changes make sure to pull changes in from upstream by doing either `git fetch upstream` then merge later or `git pull upstream` to fetch and merge in one step 12 | * Make your changes (bonus points for making changes on a new feature branch) 13 | * Push up to your account 14 | * Submit a pull request to home base at `ropensci/cchecks` 15 | 16 | ### Also, check out our [discussion forum](https://discuss.ropensci.org) 17 | -------------------------------------------------------------------------------- /.github/issue_template.md: -------------------------------------------------------------------------------- 1 | 2 | 3 |
Session Info 4 | 5 | ```r 6 | 7 | ``` 8 |
9 | -------------------------------------------------------------------------------- /.github/pull_request_template.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## Description 4 | 5 | 6 | ## Related Issue 7 | 10 | 11 | ## Example 12 | 14 | 15 | 17 | -------------------------------------------------------------------------------- /.github/workflows/R-CMD-check.yaml: -------------------------------------------------------------------------------- 1 | on: [push, pull_request] 2 | 3 | name: R-CMD-check 4 | 5 | jobs: 6 | R-CMD-check: 7 | runs-on: ${{ matrix.config.os }} 8 | 9 | name: ${{ matrix.config.os }} (${{ matrix.config.r }}) 10 | 11 | strategy: 12 | fail-fast: false 13 | matrix: 14 | config: 15 | - { os: windows-latest, r: 'latest'} 16 | - { os: macOS-latest, r: 'latest'} 17 | - { os: macOS-latest, r: 'devel'} 18 | - { os: ubuntu-16.04, r: 'latest', cran: "https://demo.rstudiopm.com/all/__linux__/xenial/latest"} 19 | 20 | env: 21 | R_REMOTES_NO_ERRORS_FROM_WARNINGS: true 22 | CRAN: ${{ matrix.config.cran }} 23 | 24 | steps: 25 | - uses: actions/checkout@v1 26 | 27 | - uses: r-lib/actions/setup-r@master 28 | with: 29 | r-version: ${{ matrix.config.r }} 30 | 31 | - uses: r-lib/actions/setup-pandoc@master 32 | 33 | - name: Cache R packages 34 | if: runner.os != 'Windows' 35 | uses: actions/cache@v1 36 | with: 37 | path: ${{ env.R_LIBS_USER }} 38 | key: ${{ runner.os }}-r-${{ matrix.config.r }}-${{ hashFiles('DESCRIPTION') }} 39 | 40 | - name: Install system dependencies 41 | if: runner.os == 'Linux' 42 | env: 43 | RHUB_PLATFORM: linux-x86_64-ubuntu-gcc 44 | run: | 45 | Rscript -e "install.packages('remotes')" -e "remotes::install_github('r-hub/sysreqs')" 46 | sysreqs=$(Rscript -e "cat(sysreqs::sysreq_commands('DESCRIPTION'))") 47 | sudo -s eval "$sysreqs" 48 | - name: Install dependencies 49 | run: Rscript -e "install.packages('remotes')" -e "remotes::install_deps(dependencies = TRUE)" -e "remotes::install_cran('rcmdcheck')" 50 | 51 | - name: Check 52 | run: Rscript -e "rcmdcheck::rcmdcheck(args = '--no-manual', error_on = 'error', check_dir = 'check')" 53 | 54 | - name: Upload check results 55 | if: failure() 56 | uses: actions/upload-artifact@master 57 | with: 58 | name: ${{ runner.os }}-r${{ matrix.config.r }}-results 59 | path: check 60 | 61 | - name: Test coverage 62 | if: matrix.config.os == 'macOS-latest' && matrix.config.r == 'latest' 63 | run: | 64 | Rscript -e 'install.packages("covr")' -e 'covr::codecov(token = "${{secrets.CODECOV_TOKEN}}")' 65 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .Rproj.user 2 | .Rhistory 3 | .RData 4 | .Rproj 5 | scotts_rules.R 6 | rules_egs.R 7 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Code of Conduct 2 | 3 | As contributors and maintainers of this project, we pledge to respect all people who 4 | contribute through reporting issues, posting feature requests, updating documentation, 5 | submitting pull requests or patches, and other activities. 6 | 7 | We are committed to making participation in this project a harassment-free experience for 8 | everyone, regardless of level of experience, gender, gender identity and expression, 9 | sexual orientation, disability, personal appearance, body size, race, ethnicity, age, or religion. 10 | 11 | Examples of unacceptable behavior by participants include the use of sexual language or 12 | imagery, derogatory comments or personal attacks, trolling, public or private harassment, 13 | insults, or other unprofessional conduct. 14 | 15 | Project maintainers have the right and responsibility to remove, edit, or reject comments, 16 | commits, code, wiki edits, issues, and other contributions that are not aligned to this 17 | Code of Conduct. Project maintainers who do not follow the Code of Conduct may be removed 18 | from the project team. 19 | 20 | Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by 21 | opening an issue or contacting one or more of the project maintainers. 22 | 23 | This Code of Conduct is adapted from the Contributor Covenant 24 | (https://contributor-covenant.org), version 1.0.0, available at 25 | https://contributor-covenant.org/version/1/0/0/ 26 | -------------------------------------------------------------------------------- /DESCRIPTION: -------------------------------------------------------------------------------- 1 | Package: cchecks 2 | Type: Package 3 | Title: Client for the cranchecks.info API 4 | Description: Client for the cranchecks.info API. 5 | Version: 0.1.8.95 6 | Authors@R: c( 7 | person("Scott", "Chamberlain", role = c("aut", "cre"), 8 | email = "sckott@protonmail.com"), 9 | person("Maëlle", "Salmon", role = "aut") 10 | ) 11 | License: MIT + file LICENSE 12 | URL: https://github.com/ropensci/cchecks, https://docs.ropensci.org/cchecks/ 13 | BugReports: https://github.com/ropensci/cchecks/issues 14 | Roxygen: list(markdown = TRUE) 15 | Encoding: UTF-8 16 | VignetteBuilder: knitr 17 | Imports: 18 | crul, 19 | jsonlite, 20 | rappdirs, 21 | tibble, 22 | cli, 23 | crayon, 24 | whoami, 25 | desc, 26 | rematch, 27 | addressable 28 | Suggests: 29 | testthat, 30 | knitr, 31 | rmarkdown, 32 | vcr, 33 | usethis 34 | RoxygenNote: 7.1.1 35 | Remotes: ropensci/addressable@main 36 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | YEAR: 2020 2 | COPYRIGHT HOLDER: Scott Chamberlain 3 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | PACKAGE := $(shell grep '^Package:' DESCRIPTION | sed -E 's/^Package:[[:space:]]+//') 2 | RSCRIPT = Rscript --no-init-file 3 | 4 | install: doc build 5 | R CMD INSTALL . && rm *.tar.gz 6 | 7 | build: 8 | R CMD build . 9 | 10 | doc: 11 | ${RSCRIPT} -e "devtools::document()" 12 | 13 | eg: 14 | ${RSCRIPT} -e "devtools::run_examples()" 15 | 16 | test: 17 | ${RSCRIPT} -e "devtools::test()" 18 | 19 | check: build 20 | _R_CHECK_CRAN_INCOMING_=FALSE R CMD CHECK --as-cran --no-manual `ls -1tr ${PACKAGE}*gz | tail -n1` 21 | @rm -f `ls -1tr ${PACKAGE}*gz | tail -n1` 22 | @rm -rf ${PACKAGE}.Rcheck 23 | 24 | check_windows: 25 | ${RSCRIPT} -e "devtools::check_win_devel(); devtools::check_win_release()" 26 | 27 | readme: 28 | ${RSCRIPT} -e "knitr::knit('README.Rmd')" 29 | 30 | vign: 31 | cd vignettes;\ 32 | ${RSCRIPT} -e "Sys.setenv(NOT_CRAN='true'); knitr::knit('cchecks.Rmd.og', output = 'cchecks.Rmd')";\ 33 | cd .. 34 | -------------------------------------------------------------------------------- /NAMESPACE: -------------------------------------------------------------------------------- 1 | # Generated by roxygen2: do not edit by hand 2 | 3 | export(cch_heartbeat) 4 | export(cch_history) 5 | export(cch_maintainers) 6 | export(cch_pkgs) 7 | export(cch_pkgs_history) 8 | export(cch_pkgs_search) 9 | export(cchn_pkg_rule_add) 10 | export(cchn_pkg_rule_delete) 11 | export(cchn_pkg_rule_get) 12 | export(cchn_pkg_rule_list) 13 | export(cchn_register) 14 | export(cchn_rule_add) 15 | export(cchn_rule_delete) 16 | export(cchn_rule_get) 17 | export(cchn_rule_list) 18 | export(cchn_rules_add) 19 | importFrom(addressable,Address) 20 | importFrom(cli,cat_line) 21 | importFrom(cli,rule) 22 | importFrom(cli,symbol) 23 | importFrom(crayon,green) 24 | importFrom(crayon,style) 25 | importFrom(crayon,yellow) 26 | importFrom(crul,AsyncVaried) 27 | importFrom(crul,HttpClient) 28 | importFrom(crul,HttpRequest) 29 | importFrom(desc,desc_get_maintainer) 30 | importFrom(jsonlite,fromJSON) 31 | importFrom(rematch,re_match) 32 | importFrom(utils,menu) 33 | importFrom(whoami,email_address) 34 | -------------------------------------------------------------------------------- /R/cch_heartbeat.R: -------------------------------------------------------------------------------- 1 | #' Get heartbeat 2 | #' 3 | #' @export 4 | #' @param ... Curl options passed to [crul::HttpClient()] 5 | #' @return list of routes 6 | #' @examples \dontrun{ 7 | #' cch_heartbeat() 8 | #' } 9 | cch_heartbeat <- function(...) { 10 | x <- ccc_GET("heartbeat", args = NULL, email = NULL, no_token = TRUE, ...) 11 | cch_parse(x, TRUE) 12 | } 13 | -------------------------------------------------------------------------------- /R/cch_history.R: -------------------------------------------------------------------------------- 1 | #' Get historical check data for all packages by date 2 | #' 3 | #' @export 4 | #' @param date (character) a date of the form `YYYY-MM-DD`. required 5 | #' @param ... Curl options passed to [crul::verb-GET] 6 | #' @return a tibble with columns: 7 | #' 8 | #' - package: character vector of package names 9 | #' - summary: character vector of JSON hash's of check summary data 10 | #' - checks: character vector of JSON hash's of checks performed 11 | #' - check_details: character vector of check details. if no check 12 | #' details the string will be "null"; if details given, then 13 | #' a JSON hash of details 14 | #' - date_updated: character vector of dates, the date the check was 15 | #' performed on 16 | #' 17 | #' @seealso [cch_pkgs_history()] 18 | #' @details This function gets historical data for all packages for a single 19 | #' day; see [cch_pkgs_history()] for last 30 days history for particular 20 | #' packages 21 | #' 22 | #' You have to do a bit of data wrangling to get this data into a 23 | #' easily sortable/filterable/etc. form 24 | #' @examples \dontrun{ 25 | #' x <- cch_history(date = "2020-04-01") 26 | #' str(x) 27 | #' lapply(x$summary[1:3], jsonlite::fromJSON) 28 | #' } 29 | cch_history <- function(date, ...) { 30 | assert(date, "character") 31 | path <- file.path("history", date) 32 | tmp <- ccc_GET_link(path, ...) 33 | z <- crul::HttpClient$new(tmp)$get(disk = hist_file(date)) 34 | f <- file(z$content) 35 | on.exit(unlink(z$content), add = TRUE) 36 | df <- suppressWarnings(jsonlite::stream_in(f)) 37 | tibble::as_tibble(df) 38 | } 39 | 40 | hist_file <- function(date) file.path(tempdir(), date) 41 | -------------------------------------------------------------------------------- /R/cch_maintainers.R: -------------------------------------------------------------------------------- 1 | #' Get maintainer based checks 2 | #' 3 | #' @export 4 | #' @param x email slug name, optional, if you pass in more than one 5 | #' we'll do async 6 | #' @param limit number of records to return. Default: 10 7 | #' @param offset record number to start at. Default: 0 8 | #' @param ... Curl options passed to [crul::HttpClient()] or 9 | #' [crul::Async()] 10 | #' @return list of info about a package(s) 11 | #' @examples \dontrun{ 12 | #' x <- cch_maintainers() 13 | #' x$data 14 | #' x$data$summary 15 | #' x$data$checks 16 | #' x$data$date_updated 17 | #' x$data$package 18 | #' x$data$url 19 | #' 20 | #' cch_maintainers("00gerhard_at_gmail.com") 21 | #' cch_maintainers(c("123saga_at_gmail.com", "13268259225_at_163.com", 22 | #' "csardi.gabor_at_gmail.com")) 23 | #' } 24 | cch_maintainers <- function(x = NULL, limit = 10, offset = 0, ...) { 25 | assert(x, "character") 26 | args <- ct(list(limit = limit, offset = offset)) 27 | path <- "maintainers" 28 | if (!is.null(x)) path <- file.path(path, x) 29 | if (length(path) > 1) { 30 | lapply(ccc_asyncGET(path, args), cch_parse, parse = TRUE) 31 | } else { 32 | cch_parse(ccc_GET(path, args, email = NULL, no_token = TRUE, ...), TRUE) 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /R/cch_pkgs.R: -------------------------------------------------------------------------------- 1 | #' Get package checks data 2 | #' 3 | #' @export 4 | #' @param x package name, optional, if you pass in more than one 5 | #' we'll do async 6 | #' @param limit number of records to return. Default: 10 7 | #' @param offset record number to start at. Default: 0 8 | #' @param ... Curl options passed to [crul::HttpClient()] or 9 | #' [crul::Async()] 10 | #' @return list of info about a package(s) 11 | #' @note this function only gets the current days checks; see 12 | #' [cch_pkgs_history()] for historical data 13 | #' @examples \dontrun{ 14 | #' x <- cch_pkgs() 15 | #' x$data 16 | #' x$data$summary 17 | #' x$data$checks 18 | #' x$data$date_updated 19 | #' x$data$package 20 | #' x$data$url 21 | #' 22 | #' cch_pkgs("geojsonio") 23 | #' cch_pkgs(c("geojsonio", "leaflet", "MASS")) 24 | #' } 25 | cch_pkgs <- function(x = NULL, limit = 10, offset = 0, ...) { 26 | assert(x, "character") 27 | args <- ct(list(limit = limit, offset = offset)) 28 | path <- "pkgs" 29 | if (!is.null(x)) path <- file.path(path, x) 30 | if (length(path) > 1) { 31 | lapply(ccc_asyncGET(path, args), cch_parse, parse = TRUE) 32 | } else { 33 | cch_parse(ccc_GET(path, args, email = NULL, no_token = TRUE, ...), TRUE) 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /R/cch_pkgs_history.R: -------------------------------------------------------------------------------- 1 | #' Get historical check data for packages 2 | #' 3 | #' @export 4 | #' @param x package name, required, if you pass in more than one 5 | #' we'll do async 6 | #' @inheritParams cch_pkgs 7 | #' @return list of info about a package(s) 8 | #' @details this function gets historical data; for current day check data only 9 | #' see [cch_pkgs()] 10 | #' 11 | #' data is only available for 30 days prior to today's date, see the 12 | #' [cch_history()] function for older data 13 | #' @examples \dontrun{ 14 | #' x <- cch_pkgs_history(x = "geojsonio") 15 | #' x 16 | #' x$data 17 | #' x$data$package 18 | #' x$data$history 19 | #' x$data$history$summary 20 | #' x$data$history$summary$any 21 | #' x$data$history$check_details 22 | #' 23 | #' # many packages 24 | #' res <- cch_pkgs_history(c("geojsonio", "leaflet", "MASS")) 25 | #' res 26 | #' 27 | #' # pagination 28 | #' cch_pkgs_history(x = "geojsonio", limit = 3) 29 | #' cch_pkgs_history(x = "geojsonio", limit = 3, offset = 4) 30 | #' } 31 | cch_pkgs_history <- function(x, limit = 30, offset = 0, ...) { 32 | assert(x, "character") 33 | args <- ct(list(limit = limit, offset = offset)) 34 | path <- "pkgs/%s/history" 35 | path <- sprintf(path, x) 36 | if (length(path) > 1) { 37 | lapply(ccc_asyncGET(path, args), each_story) 38 | } else { 39 | each_story(ccc_GET(path, args, email = NULL, no_token = TRUE, ...)) 40 | } 41 | } 42 | 43 | each_story <- function(x, parse = TRUE) { 44 | tmp <- cch_parse(x, parse) 45 | tmp$data$history <- tibble::as_tibble(tmp$data$history) 46 | return(tmp) 47 | } 48 | -------------------------------------------------------------------------------- /R/cch_pkgs_search.R: -------------------------------------------------------------------------------- 1 | #' Search historical package check data 2 | #' 3 | #' @export 4 | #' @param q (character) full text query string 5 | #' @param package (character) a package name. limit results to a single 6 | #' package, e.g, `package="taxize"` 7 | #' @param one_each (logical) if `TRUE`, return a single result for each package; 8 | #' useful if you want to find out what packages match a particular query, and 9 | #' don't care which day that match happened. default: `FALSE` 10 | #' @param fields (character) vector of fields to return, e.g., 11 | #' `fields=c("package", "check_details")` 12 | #' @inheritParams cch_pkgs 13 | #' @return list of info about a package(s) 14 | #' @examples \dontrun{ 15 | #' x <- cch_pkgs_search(q = "memory") 16 | #' x 17 | #' x$data 18 | #' x$data$package 19 | #' x$data 20 | #' x$data$summary 21 | #' x$data$summary$any 22 | #' x$data$check_details 23 | #' 24 | #' # restrict returned fields 25 | #' res <- cch_pkgs_search("memory", fields = c("package", "check_details")) 26 | #' res$data$check_details$output[1] 27 | #' grepl('memory', res$data$check_details$output[1]) 28 | #' 29 | #' # one each, one record per package 30 | #' res <- cch_pkgs_search("memory", one_each = TRUE, 31 | #' fields = c("package", "date_updated")) 32 | #' res 33 | #' 34 | #' # pagination 35 | #' cch_pkgs_search("memory", limit = 3) 36 | #' cch_pkgs_search("memory", limit = 3, offset = 4) 37 | #' } 38 | cch_pkgs_search <- function(q, package = NULL, one_each = FALSE, 39 | fields = NULL, limit = 30, offset = 0, ...) { 40 | 41 | assert(q, "character") 42 | assert(package, "character") 43 | assert(fields, "character") 44 | assert(one_each, "logical") 45 | if (!is.null(fields)) fields <- paste0(fields, collapse=",") 46 | args <- ct(list(q = q, package = package, one_each = as_log(one_each), 47 | fields = fields, limit = limit, offset = offset)) 48 | res <- ccc_GET("search", args, email = NULL, no_token = TRUE, ...) 49 | tmp <- cch_parse(res, TRUE) 50 | tmp$data <- tibble::as_tibble(tmp$data) 51 | return(tmp) 52 | } 53 | -------------------------------------------------------------------------------- /R/cchecks-package.R: -------------------------------------------------------------------------------- 1 | #' @title cchecks 2 | #' @description Client for the cranchecks.info API 3 | #' @section Docs: 4 | #' See 5 | #' 6 | #' @section Historical data: 7 | #' There's an important shortcoming of historical data. The links in the 8 | #' historical data in the `checks` field are not date specific. If you go to a 9 | #' link in historical data, for example for April 2nd, 2020, links in that set 10 | #' of data link to whatever the current check data is for that package. The 11 | #' `check_details` field is date specific though; the text is scraped from the 12 | #' package checks page each day and stored, so you can count on that to be date 13 | #' specific. There are sometimes links to further checks, often of compiled 14 | #' packages on various types of checks that CRAN runs; we do not have those 15 | #' check results - we could get them but have not take the time to sort that 16 | #' out. 17 | #' 18 | #' @importFrom jsonlite fromJSON 19 | #' @importFrom crul HttpClient HttpRequest AsyncVaried 20 | #' @importFrom cli symbol cat_line rule 21 | #' @importFrom crayon yellow green yellow style 22 | #' @importFrom utils menu 23 | #' @importFrom whoami email_address 24 | #' @importFrom desc desc_get_maintainer 25 | #' @importFrom rematch re_match 26 | #' @importFrom addressable Address 27 | #' @name cchecks-package 28 | #' @aliases cchecks 29 | #' @docType package 30 | #' @author Scott Chamberlain \email{sckott@@protonmail.com} 31 | #' @keywords package 32 | NULL 33 | -------------------------------------------------------------------------------- /R/cchn_register.R: -------------------------------------------------------------------------------- 1 | #' Notifications: register your email address and get a token 2 | #' 3 | #' @export 4 | #' @param email (character) email address to use for interaction with 5 | #' the CRAN checks API. If no email address is given, we go through a few 6 | #' steps: check for the cached file mentioned below for any emails; use 7 | #' [whoami::email_address()]; if the location you are running this in is 8 | #' a package, we look for the maintainer's email address in the package. 9 | #' @param token (character) your CRAN checks API token. you shouldn't need 10 | #' to pass a token here. if you used [cchn_register()] your token should 11 | #' be cached 12 | #' @param ... Curl options passed to [crul::verb-GET] 13 | #' @return `NULL` - nothing returned 14 | #' @details We cache a file with email addresses and tokens at the path 15 | #' `file.path(rappdirs::user_data_dir("cranchecks", "cchecks"), "emails.csv")` 16 | #' You can run that in R to get the path for the file on your machine. 17 | #' 18 | #' To get a new token for an email address that was previously registered, 19 | #' go to the file above and delete the line with the email address and token 20 | #' for the email address in question; remember to save the change. 21 | #' Then when you run `cchn_register()` again for that email you can get 22 | #' a new token. 23 | #' 24 | #' To add an email address that was validated before (probably on 25 | #' another machine), to the configuration file, call this function 26 | #' with the ‘email’ and ‘token’ arguments. 27 | cchn_register <- function(email = NULL, token = NULL, ...) { 28 | if (is.null(email) || is.null(token)) { 29 | if (!interactive()) { 30 | stop("No email or no token and not in interactive mode") 31 | } 32 | return(interactive_validate_email(email, token, ...)) 33 | } else { 34 | valid_email(email) 35 | } 36 | add_token(email, token) 37 | message("Token added for ", sQuote(email)) 38 | cat("\n") 39 | } 40 | -------------------------------------------------------------------------------- /R/cchn_rules.R: -------------------------------------------------------------------------------- 1 | #' Notifications: add, list, get, delete notification rules 2 | #' 3 | #' @name cchn_rules 4 | #' @param status (character) a check status, one of: error, warn, note, fail 5 | #' @param platform (character) a platform, a string to match against the 6 | #' platform strings used by cran checks. e.g., "osx" would match any osx 7 | #' platform check results, whereas you could limit the rule to just a single 8 | #' specific platform by using the target platforms exact string 9 | #' "r-oldrel-osx-x86_64". Leave as `NULL` (the default) to match all 10 | #' platforms. 11 | #' @param time (integer) number of days 12 | #' @param regex (character) a regex string 13 | #' @param package (character) a package name. if `NULL`, we attempt to 14 | #' get the package name from the working directory, and fail out if there's 15 | #' not a valid package structure/package name 16 | #' @param email (character) email address to use for interaction with 17 | #' the CRAN checks API. we use the email address in the maintainers slot 18 | #' of the DESCRIPTION file of your working directory. you can supply an 19 | #' email address instead 20 | #' @param path (character) path to a directory containing an R package 21 | #' @param id (integer) a rule id. note that you can not get or delete 22 | #' rules that are not yours. required 23 | #' @param rules (list) a list of rules. each element in the list must 24 | #' be a named list, in which each must have a "package", and a set of 25 | #' rules (see below) 26 | #' @param quiet (logical) suppress messages? default: `FALSE` 27 | #' @param ... Curl options passed to [crul::verb-GET], [crul::verb-POST], or 28 | #' [crul::verb-DELETE] 29 | #' 30 | #' @details 31 | #' 32 | #' Functions prefixed with `cchn_pkg_` operate within a package 33 | #' directory. That is, your current working directory is an R 34 | #' package, and is the package for which you want to handle CRAN checks 35 | #' notifications. These functions make sure that you are inside of 36 | #' an R package, and use the email address and package name based 37 | #' on the directory you're in. 38 | #' 39 | #' Functions prefixed with just `cchn_` do not operate within a package. 40 | #' These functions do not guess package name at all, but require the user 41 | #' to supply a package name (for those functions that require a package name); 42 | #' and instead of guessing an email address from your package, we guess email 43 | #' from the cached cchecks email file. 44 | #' 45 | #' - `cchn_pkg_rule_add()`/`cchn_rule_add()`: add a rule, one rule per 46 | #' function call 47 | #' - `cchn_rules_add()`: add many rules at once; no option for package context 48 | #' - `cchn_pkg_rule_get()`/`cchn_rule_get()`: get a rule by rule id (see 49 | #' `cchn_pkg_rule_list()`/`cchn_rule_list()` to get ids; can only get rules for 50 | #' the authenticated user) 51 | #' - `cchn_pkg_rule_list()`/`cchn_rule_list()`: list rules for the 52 | #' authenticated user - `cchn_pkg_rule_list()` lists rules only for the package 53 | #' in question, while `cchn_rule_list()` lists all rules for the user (email) 54 | #' - `cchn_pkg_rule_delete()`/`cchn_rule_delete()`: delete a rule by rule id 55 | #' (only those for the authenticated user) 56 | #' 57 | #' @section example rules: 58 | #' 59 | #' Note that the first parameter `package` is left out for brevity 60 | #' 61 | #' - ERROR for at least 1 day across all platforms 62 | #' - `cchn_rule_add(status = 'error')` 63 | #' - ERROR for 3 days in a row across 2 or more platforms 64 | #' - `cchn_rule_add(status = 'error', time = 3, platform = 2)` 65 | #' - ERROR for 2 days in a row on all osx platforms 66 | #' - `cchn_rule_add(status = 'error', time = 2, platform = "osx")` 67 | #' - ERROR for 2 days in a row on all release R versions 68 | #' - `cchn_rule_add(status = 'error', time = 2, platform = "release")` 69 | #' - WARN for 4 days in a row on any platform except Solaris 70 | #' - `cchn_rule_add(status = 'warn', time = 4, platform = "-solaris")` 71 | #' - WARN for 2 days in a row across 9 or more platforms 72 | #' - `cchn_rule_add(status = 'warn', time = 2, platform = 10)` 73 | #' - NOTE on any osx platform 74 | #' - `cchn_rule_add(status = 'note', platform = "osx")` 75 | #' - NOTE on any platform 76 | #' - `cchn_rule_add(status = 'note')` 77 | #' - error details contain regex 'install' 78 | #' - `cchn_rule_add(regex = "install")` 79 | #' 80 | #' @return 81 | #' 82 | #' - `cchn_pkg_rule_add()`/`cchn_rule_add()`/`cchn_rules_add()`: message about 83 | #' the rule added, and a note about using `cchn_rule_list()` to list your rules 84 | #' - `cchn_pkg_rule_get()`/`cchn_rule_get()`: list with elements `error` and 85 | #' `data` (a list of the parts of the rule) 86 | #' - `cchn_pkg_rule_list()`/`cchn_rule_list()`: list with elements `error` and 87 | #' `data` (a data.frame of all the rules associated with your email) 88 | #' - `cchn_pkg_rule_delete()`/`cchn_rule_delete()`: if deletion works, a 89 | #' message saying "ok" 90 | #' 91 | #' @examples \dontrun{ 92 | #' ## Workflow 1: within a package directory 93 | #' # (x <- cchn_pkg_rule_list()) 94 | #' # if (length(x$data$id) > 0) { 95 | #' # cchn_pkg_rule_get(x$data$id[1]) 96 | #' # cchn_pkg_rule_delete(x$data$id[1]) 97 | #' # cchn_pkg_rule_get(id = x$data$id[1]) 98 | #' # } 99 | #' 100 | #' ## Workflow 2: not in a package directory 101 | #' # (x <- cchn_rule_list()) 102 | #' # if (length(x$data$id) > 0) { 103 | #' # cchn_rule_get(x$data$id[1]) 104 | #' # cchn_rule_delete(x$data$id[1]) 105 | #' # cchn_rule_get(id = x$data$id[1]) 106 | #' # } 107 | #' 108 | #' ## cchn_pkg_rule_add: add a rule - guesses the package name 109 | #' ## you can specify the package name instead 110 | #' # cchn_pkg_rule_add(status = "note", platform = 3, 111 | #' # email = "some-email") 112 | #' ## cchn_rule_add: add a rule - not in package context, must 113 | #' ## specify the package name 114 | #' # cchn_rule_add(package = "foobar", status = "note", platform = 3, 115 | #' # email = "some-email") 116 | #' 117 | #' ## cchn_pkg_rule_add: should guess package name and email 118 | #' # cchn_pkg_rule_add(status = "note", platform = 3) 119 | #' 120 | #' ## cchn_rule_add: package name must be supplied. takes first email 121 | #' ## from cached emails.csv file, see `?cchn_register` for more 122 | #' # cchn_rule_add(package = "foobar", status = "warn", platform = 2) 123 | #' 124 | #' ## cchn_rules_add: add many rules at once 125 | #' ## no package context here, email and package names must be given 126 | #' # pkg <- "charlatan" 127 | #' # rules <- list( 128 | #' # list(package = pkg, status = "warn"), 129 | #' # list(package = pkg, status = "error", time = 4) 130 | #' # ) 131 | #' # cchn_rules_add(rules, "your-email", verbose = TRUE) 132 | #' } 133 | NULL 134 | -------------------------------------------------------------------------------- /R/email-utils.R: -------------------------------------------------------------------------------- 1 | # much of the below code adapted from r-hub/rhub 2 | add_token <- function(email, token) { 3 | file <- email_file_path() 4 | if (!file.exists(file)) { 5 | parent <- dirname(file) 6 | if (!file.exists(parent)) dir.create(parent, recursive = TRUE) 7 | toks <- data.frame(V1 = character(), V2 = character(), 8 | stringsAsFactors = FALSE) 9 | } else { 10 | toks <- utils::read.csv(file, stringsAsFactors = FALSE, header = FALSE) 11 | } 12 | if (email %in% toks[, 1]) { 13 | toks[which(email == toks[,1]), 2] <- token 14 | } else { 15 | toks <- rbind(toks, c(email, token)) 16 | } 17 | utils::write.table(toks, file = file, sep = ",", col.names = FALSE, 18 | row.names = FALSE) 19 | } 20 | 21 | email_file_path <- function() { 22 | if (Sys.getenv("CCHECKS_TESTING", "FALSE")) { 23 | Sys.getenv("CCHECKS_TESTING_EMAIL_FILE_PATH", "") 24 | } else { 25 | file.path(rappdirs::user_data_dir("cranchecks", "cchecks"), 26 | "emails.csv") 27 | } 28 | } 29 | 30 | request_token <- function(email, ...) { 31 | args <- ct(list(email = email)) 32 | ccc_GET("notifications/token", args, email = NULL, no_token = TRUE, ...) 33 | } 34 | 35 | cchn_valid <- function(token = NULL) { 36 | z <- tryCatch(cchn_rule_list(token = token), error = function(e) e) 37 | !inherits(z, "error") 38 | } 39 | 40 | token_registered <- function(email) { 41 | file <- email_file_path() 42 | if (file.exists(file)) { 43 | toks <- utils::read.csv(file, stringsAsFactors = FALSE, header = FALSE) 44 | if (email %in% toks[, 1]) { 45 | token <- toks[which(email == toks[,1]), 2] 46 | if (cchn_valid(token)) { 47 | message("email '", email, "' already registered") 48 | return(TRUE) 49 | } # if FALSE, we return FALSE below and ask for new token 50 | } 51 | } 52 | return(FALSE) 53 | } 54 | 55 | fetch_token <- function(email) { 56 | toks <- utils::read.csv(email_file_path(), stringsAsFactors = FALSE, 57 | header = FALSE) 58 | toks[which(email == toks[,1]), 2] 59 | } 60 | 61 | interactive_validate_email <- function(email, token, path = ".", ...) { 62 | if (is.null(email)) email <- get_email_to_validate(path) 63 | stopifnot("'email' is not a valid email" = grepl(".@.", email)) 64 | 65 | if (token_registered(email)) { 66 | return(cchn_register(email, fetch_token(email))) 67 | } 68 | 69 | if (is.null(token)) { 70 | request_token(email, ...) 71 | message(crayon::yellow( 72 | "Check your emails for the CRAN checks token (may not arrive immediately)\n", 73 | "Paste in the token without quotes" 74 | )) 75 | token <- readline("Token: ") 76 | } 77 | stopifnot(grepl("[a-zA-Z0-9]{6}", token, perl = TRUE)) 78 | cchn_register(email, token) 79 | } 80 | 81 | get_email_to_validate <- function(path) { 82 | valid <- list_validated_emails2(msg_if_empty = FALSE) 83 | guess <- whoami::email_address() 84 | maint <- tryCatch(get_maintainer_email(path), error = function(e) NULL) 85 | 86 | choices <- rbind( 87 | if (nrow(valid)) cbind(valid = TRUE, valid), 88 | if (!is.null(guess) && ! guess %in% valid$email) { 89 | tibble::tibble(valid = FALSE, email = guess, token = NA) 90 | }, 91 | if (!is.null(maint) && ! maint %in% valid$email && maint != guess) { 92 | tibble::tibble(valid = FALSE, email = maint, token = NA) 93 | }, 94 | tibble::tibble(valid = NA, email = "New email address", token = NA) 95 | ) 96 | 97 | ## Only show the menu if there is more than one thing there 98 | if (nrow(choices) != 1) { 99 | choices_str <- paste( 100 | sep = " ", 101 | ifelse( 102 | choices$valid & !is.na(choices$valid), 103 | crayon::green(symbol$tick), 104 | " " 105 | ), 106 | choices$email 107 | ) 108 | 109 | cat("\n") 110 | title <- crayon::yellow(paste0( 111 | symbol$line, symbol$line, 112 | " Choose email address to (re)validate (or 0 to exit)" 113 | )) 114 | ch <- menu(choices_str, title = title) 115 | 116 | if (ch == 0) stop("Cancelled email validation", call. = FALSE) 117 | 118 | } else { 119 | ch <- 1 120 | } 121 | 122 | ## Get another address if that is selected 123 | if (is.na(choices$valid[ch])) { 124 | cat("\n") 125 | email <- readline("Email address: ") 126 | } else { 127 | email <- choices$email[ch] 128 | } 129 | } 130 | 131 | list_validated_emails2 <- function(msg_if_empty = TRUE) { 132 | file <- email_file_path() 133 | res <- if (file.exists(file)) { 134 | structure( 135 | utils::read.csv(file, stringsAsFactors = FALSE, header = FALSE), 136 | names = c("email", "token") 137 | ) 138 | } else { 139 | data.frame( 140 | email = character(), 141 | token = character(), 142 | stringsAsFactors = FALSE 143 | ) 144 | } 145 | if (interactive() && nrow(res) == 0) { 146 | if (msg_if_empty) message("No validated emails found.") 147 | invisible(res) 148 | } else { 149 | res 150 | } 151 | } 152 | 153 | stract <- function(str, pattern) regmatches(str, regexpr(pattern, str)) 154 | 155 | parse_email <- function(x) { 156 | unname( 157 | rematch::re_match(pattern = "<(?[^>]+)>", x)[, "email"] 158 | ) 159 | } 160 | 161 | get_maintainer_email <- function(path) { 162 | path <- normalizePath(path, mustWork = TRUE) 163 | if (file.info(path)$isdir) { 164 | if (!file.exists(file.path(path, "DESCRIPTION"))) { 165 | stop("No 'DESCRIPTION' file found") 166 | } 167 | parse_email(desc::desc_get_maintainer(path)) 168 | } else { 169 | stop("does not appear to be a package") 170 | } 171 | } 172 | get_email <- function(quiet = FALSE) { 173 | assert(quiet, "logical") 174 | file <- email_file_path() 175 | if (!file.exists(file)) 176 | stop("emails.csv file not found; see ?cchn_register", call. = FALSE) 177 | df <- utils::read.csv(file, stringsAsFactors = FALSE, header = FALSE) 178 | if (NROW(df) == 0) { 179 | stop("emails.csv file empty; see ?cchn_register", call. = FALSE) 180 | } 181 | if (NROW(df) > 1) { 182 | if (!quiet) { 183 | warning("> 1 emails found in emails.csv; ", 184 | "using first email; ", 185 | "re-arrange emails in file to set a different preferred email", 186 | call. = FALSE) 187 | } 188 | } 189 | return(df[,1][1]) 190 | } 191 | 192 | assert_validated_email_for_check <- function(email) { 193 | token <- email_get_token(email) 194 | if (is.null(token)) { 195 | stop(paste(collapse = "\n", strwrap(indent = 2, exdent = 2, paste( 196 | sQuote(crayon::green(email)), "is not validated, see ?cchn_register" 197 | )))) 198 | } 199 | } 200 | 201 | email_get_token <- function(email) { 202 | file <- email_file_path() 203 | if (!file.exists(file)) return(NULL) 204 | 205 | tokens <- utils::read.csv(file, stringsAsFactors = FALSE, header = FALSE) 206 | if (!email %in% tokens[,1]) return(NULL) 207 | 208 | tokens[match(email, tokens[,1]), 2] 209 | } 210 | 211 | email_token_check <- function(email = NULL) { 212 | if (is.na(email)) stop("Cannot get email address from package") 213 | assert_validated_email_for_check(email) 214 | } 215 | 216 | package_name <- function(package, path = ".") { 217 | if (is.null(package)) { 218 | if (!desc::desc_has_fields("Package", file = path)) 219 | stop("could not find package name") 220 | package <- desc::desc_get_field("Package", file = path) 221 | } 222 | return(package) 223 | } 224 | 225 | mssg <- function(package, rule) { 226 | cli::rule( 227 | left = "success ", line = 2, line_col = "blue", width = 30 228 | ) 229 | cli::cat_line( 230 | paste("package:", crayon::style(package, "lightblue")) 231 | ) 232 | cli::cat_line( 233 | paste("rule:", crayon::style(rule, "purple")) 234 | ) 235 | cli::cat_line("list rules: ", 236 | crayon::style("cchn_pkg_rule_list()/cchn_rule_list()", "underline")) 237 | } 238 | mssg2 <- function(package, rule) { 239 | cli::rule( 240 | left = "success ", line = 2, line_col = "blue", width = 30 241 | ) 242 | cli::cat_line( 243 | paste("package:", crayon::style(package, "lightblue")) 244 | ) 245 | cli::cat_line( 246 | paste("rule:", crayon::style(rule, "purple")) 247 | ) 248 | } 249 | mssg_get_rules <- function() { 250 | cli::cat_line("list rules: ", crayon::style("cchn_rule_list()", "underline")) 251 | } 252 | 253 | check_within_a_pkg <- function(path = ".") { 254 | x <- tryCatch(desc::desc(file = path), error = function(e) e) 255 | !inherits(x, "error") 256 | } 257 | 258 | valid_email <- function(email) { 259 | assert(email, "character") 260 | if (!grepl(".@.", email)) stop("`email` is not a valid email") 261 | # x <- Address$new(email) 262 | # if (!x$valid()) stop("invalid email address: ", email, call. = FALSE) 263 | # if (!x$valid()) stop(x$fail(), call. = FALSE) 264 | } 265 | -------------------------------------------------------------------------------- /R/http.R: -------------------------------------------------------------------------------- 1 | ccc_base <- function() "https://cranchecks.info" 2 | # ccc_base <- function() "http://localhost:8834" 3 | 4 | cchecks_ua <- function() { 5 | versions <- c( 6 | paste0("r-curl/", utils::packageVersion("curl")), 7 | paste0("crul/", utils::packageVersion("crul")), 8 | sprintf("rOpenSci(cchecks/%s)", utils::packageVersion("cchecks")) 9 | ) 10 | paste0(versions, collapse = " ") 11 | } 12 | 13 | check_token <- function(email) { 14 | toks <- utils::read.csv(email_file_path(), stringsAsFactors = FALSE, 15 | header = FALSE) 16 | toks[which(email == toks[,1]), 2] 17 | } 18 | 19 | ccc_GET <- function(path, args, email = NULL, no_token = FALSE, ...) { 20 | headers <- list() 21 | if (!no_token) { 22 | token <- check_token(email) 23 | headers <- list(Authorization = paste("Bearer", token)) 24 | } 25 | cli <- crul::HttpClient$new( 26 | url = file.path(ccc_base(), path), 27 | opts = list(useragent = cchecks_ua(), ...), 28 | headers = headers 29 | ) 30 | temp <- cli$get(query = args) 31 | err_catcher(temp) 32 | x <- temp$parse("UTF-8") 33 | return(x) 34 | } 35 | 36 | ccc_GET_link <- function(path, ...) { 37 | cli <- crul::HttpClient$new( 38 | url = file.path(ccc_base(), path), 39 | opts = list(useragent = cchecks_ua(), followlocation = 1, ...) 40 | ) 41 | temp <- cli$get() 42 | err_catcher(temp) 43 | return(temp$url) 44 | } 45 | 46 | ccc_DELETE <- function(path, email = NULL, ...) { 47 | headers <- list() 48 | token <- check_token(email) 49 | if (!is.null(token)) { 50 | headers <- list(Authorization = paste("Bearer", token)) 51 | } 52 | cli <- crul::HttpClient$new( 53 | url = file.path(ccc_base(), path), 54 | opts = list(useragent = cchecks_ua(), ...), 55 | headers = headers 56 | ) 57 | temp <- cli$delete() 58 | err_catcher(temp) 59 | return(temp) 60 | } 61 | 62 | ccc_POST <- function(path, body, email = NULL, ...) { 63 | headers <- list() 64 | token <- check_token(email) 65 | if (!is.null(token)) { 66 | headers <- list(Authorization = paste("Bearer", token)) 67 | } 68 | cli <- crul::HttpClient$new( 69 | url = file.path(ccc_base(), path), 70 | opts = list(useragent = cchecks_ua(), ...), 71 | headers = c(headers, `Content-Type` = "application/json") 72 | ) 73 | temp <- cli$post(body = body, encode = "json") 74 | err_catcher(temp) 75 | x <- temp$parse("UTF-8") 76 | return(x) 77 | } 78 | 79 | ccc_asyncGET <- function(path, args, ...) { 80 | path <- file.path(ccc_base(), path) 81 | reqs <- lapply(path, function(z) { 82 | crul::HttpRequest$new(url = z, opts = list(useragent = cchecks_ua()) 83 | )$get(query = args) 84 | }) 85 | out <- AsyncVaried$new(.list = reqs) 86 | out$request() 87 | out$parse("UTF-8") 88 | } 89 | 90 | err_catcher <- function(x) { 91 | if (x$status_code > 201) { 92 | if (x$status_code == 204) return(NULL) 93 | if (grepl("xml", x$response_headers$`content-type`)) { 94 | txt <- x$parse("UTF-8") 95 | if (grepl("NoSuchKey", txt) || x$status_code == 404) { 96 | mssg <- "error in fetching Amazon S3 file: `date` not found" 97 | } else { 98 | mssg <- "error in fetching Amazon S3 file: unknown reason" 99 | } 100 | } 101 | if (grepl("json", x$response_headers$`content-type`)) { 102 | xx <- jsonlite::fromJSON(x$parse("UTF-8")) 103 | mssg <- xx$error 104 | } 105 | stop(sprintf("(%s) ", x$status_code), mssg, call. = FALSE) 106 | } 107 | } 108 | 109 | cch_parse <- function(x, parse) { 110 | jsonlite::fromJSON(x, parse) 111 | } 112 | -------------------------------------------------------------------------------- /R/rule-add.R: -------------------------------------------------------------------------------- 1 | #' @export 2 | #' @rdname cchn_rules 3 | cchn_rules_add <- function(rules, email, quiet = FALSE, ...) { 4 | if (!is.null(email)) valid_email(email) 5 | if (is.null(email)) email <- get_email(quiet = quiet) 6 | email_token_check(email) 7 | assert(rules, "list") 8 | # check each rule 9 | rule_names <- c("package", "status", "time", "platforms", "regex") 10 | for (i in seq_along(rules)) { 11 | if (!inherits(rules[[i]], "list")) 12 | stop("each element of `rules` must be a list", call. = FALSE) 13 | if (!all(names(rules[[i]]) %in% rule_names)) { 14 | stop("one or more names in the list not in acceptable set: ", 15 | paste0(rule_names, collapse = ", "), 16 | call. = FALSE) 17 | } 18 | } 19 | out <- ccc_POST("notifications/rules", body = rules, email = email, ...) 20 | if (!quiet) { 21 | for (i in seq_along(rules)) { 22 | mssg2(rules[[i]]$package, rule = jsonlite::toJSON(rules[[i]], 23 | auto_unbox = TRUE)) 24 | cat("\n") 25 | } 26 | mssg_get_rules() 27 | } 28 | return(cch_parse(out, TRUE)) 29 | } 30 | #' @export 31 | #' @rdname cchn_rules 32 | cchn_pkg_rule_add <- function(status = NULL, platform = NULL, 33 | time = NULL, regex = NULL, package = NULL, email = NULL, 34 | path = ".", quiet = FALSE, ...) { 35 | 36 | if (is.null(email)) email <- get_maintainer_email(path) 37 | package <- package_name(package, path = path) 38 | rule_add(package, status, platform, time, regex, email, quiet, ...) 39 | } 40 | #' @export 41 | #' @rdname cchn_rules 42 | cchn_rule_add <- function(package, status = NULL, platform = NULL, 43 | time = NULL, regex = NULL, email = NULL, quiet = FALSE, ...) { 44 | 45 | if (is.null(email)) email <- get_email(quiet = quiet) 46 | rule_add(package, status, platform, time, regex, email, quiet, ...) 47 | } 48 | rule_add <- function(package, status, platform, time, regex, email, quiet, ...) { 49 | valid_email(email) 50 | email_token_check(email) 51 | assert(package, "character") 52 | assert(status, "character") 53 | assert(platform, c("numeric", "integer", "character")) 54 | assert(time, c("numeric", "integer")) 55 | assert(regex, "character") 56 | assert(quiet, "logical") 57 | body <- ct(list(package = package, status = status, platforms = platform, 58 | time = time, regex = regex)) 59 | out <- ccc_POST("notifications/rules", body = list(body), email = email, ...) 60 | if (!quiet) mssg(package, rule = jsonlite::toJSON(body, auto_unbox = TRUE)) 61 | return(cch_parse(out, TRUE)) 62 | } 63 | -------------------------------------------------------------------------------- /R/rule-delete.R: -------------------------------------------------------------------------------- 1 | rule_delete <- function(id, email, ...) { 2 | valid_email(email) 3 | email_token_check(email) 4 | assert(id, c('integer', 'numeric')) 5 | stopifnot("id length can not be 0" = length(id) > 0) 6 | x <- ccc_DELETE(path = file.path("notifications/rules", id), 7 | email = email, ...) 8 | if (x$status_code == 204) message("ok") 9 | } 10 | #' @export 11 | #' @rdname cchn_rules 12 | cchn_pkg_rule_delete <- function(id, email = NULL, path = ".", ...) { 13 | check_within_a_pkg(path) 14 | if (is.null(email)) email <- get_maintainer_email(path) 15 | rule_delete(id, email, ...) 16 | } 17 | #' @export 18 | #' @rdname cchn_rules 19 | cchn_rule_delete <- function(id, email = NULL, quiet = FALSE, ...) { 20 | if (is.null(email)) email <- get_email(quiet = quiet) 21 | rule_delete(id, email, ...) 22 | } 23 | -------------------------------------------------------------------------------- /R/rule-get.R: -------------------------------------------------------------------------------- 1 | rule_get <- function(id, email, ...) { 2 | valid_email(email) 3 | email_token_check(email) 4 | assert(id, c('integer', 'numeric')) 5 | if (!length(id) > 0) stop("id length can not be 0", call. = FALSE) 6 | x <- ccc_GET(path = file.path("notifications/rules", id), list(), 7 | email = email, ...) 8 | cch_parse(x, TRUE) 9 | } 10 | #' @export 11 | #' @rdname cchn_rules 12 | cchn_pkg_rule_get <- function(id, email = NULL, path = ".", ...) { 13 | check_within_a_pkg(path) 14 | if (is.null(email)) email <- get_maintainer_email(path) 15 | rule_get(id, email, ...) 16 | } 17 | #' @export 18 | #' @rdname cchn_rules 19 | cchn_rule_get <- function(id, email = NULL, quiet = FALSE, ...) { 20 | if (is.null(email)) email <- get_email(quiet = quiet) 21 | rule_get(id, email, ...) 22 | } 23 | -------------------------------------------------------------------------------- /R/rule-list.R: -------------------------------------------------------------------------------- 1 | # rule list 2 | rule_list <- function(email, args = list(), ...) { 3 | valid_email(email) 4 | email_token_check(email) 5 | x <- ccc_GET("notifications/rules", args, email = email, ...) 6 | cch_parse(x, TRUE) 7 | } 8 | #' @export 9 | #' @rdname cchn_rules 10 | cchn_pkg_rule_list <- function(email = NULL, path = ".", ...) { 11 | check_within_a_pkg(path) 12 | if (is.null(email)) email <- get_maintainer_email(path) 13 | package <- desc::desc_get_field("Package", file = path) 14 | rule_list(email, args = list(package = package), ...) 15 | } 16 | #' @export 17 | #' @rdname cchn_rules 18 | cchn_rule_list <- function(email = NULL, quiet = FALSE, ...) { 19 | if (is.null(email)) email <- get_email(quiet = quiet) 20 | rule_list(email, ...) 21 | } 22 | -------------------------------------------------------------------------------- /R/zzz.R: -------------------------------------------------------------------------------- 1 | ct <- function(l) Filter(Negate(is.null), l) 2 | 3 | assert <- function(x, y) { 4 | if (!is.null(x)) { 5 | if (!inherits(x, y)) { 6 | stop(deparse(substitute(x)), " must be of class ", 7 | paste0(y, collapse = ", "), call. = FALSE) 8 | } 9 | } 10 | } 11 | 12 | as_log <- function(x) { 13 | if (is.null(x)) return(x) 14 | if (x) "true" else "false" 15 | } 16 | -------------------------------------------------------------------------------- /README-not.md: -------------------------------------------------------------------------------- 1 | cchecks 2 | ======= 3 | 4 | 5 | 6 | [![R-CMD-check](https://github.com/ropensci/cchecks/workflows/R-CMD-check/badge.svg)](https://github.com/ropensci/cchecks/actions/) 7 | [![codecov.io](https://codecov.io/github/ropensci/cchecks/coverage.svg?branch=master)](https://codecov.io/github/ropensci/cchecks?branch=master) 8 | 9 | R client for the CRAN checks API at 10 | 11 | [CRAN checks API docs][docs] 12 | 13 | authentication is only needed for the CRAN checks API for the functions that start with `cchn` 14 | 15 | See https://docs.ropensci.org/cchecks for full documentation on `cchecks` 16 | 17 | ## Install 18 | 19 | 20 | ```r 21 | remotes::install_github("ropensci/cchecks") 22 | ``` 23 | 24 | 25 | ```r 26 | library("cchecks") 27 | ``` 28 | 29 | ## heartbeat 30 | 31 | - `cch_heartbeat()` 32 | 33 | ## packages 34 | 35 | - current day package check data: `cch_pkgs()` or `cch_pkgs("packagename")` 36 | - historical package check data (30 days back): `cch_pkgs_history()` 37 | - historical package check data for all packages by day: `cch_history()` 38 | - search historical data: `cch_pkgs_search()` 39 | 40 | There's an important shortcoming of historical data. The links in the historical 41 | data in the `checks` field are not date specific. If you go to a link in historical 42 | data, for example for April 2nd, 2020, links in that set of data link to whatever 43 | the current check data is for that package. The `check_details` field is 44 | date specific though; the text is scraped from the package checks page each day 45 | and stored, so you can count on that to be date specific. There are sometimes 46 | links to further checks, often of compiled packages on various types of checks 47 | that CRAN runs; we do not have those check results - we could get them but 48 | have not take the time to sort that out. 49 | 50 | 51 | ## maintainers 52 | 53 | - all maintainers: `cch_maintainers()` 54 | - maintainers by email: `cch_maintainers("maelle.salmon_at_yahoo.se")` 55 | 56 | ## notifications 57 | 58 | Functions for working with notifications are all prefixed with `cchn`. 59 | 60 | `cchn` functions are designed to be used from within an R package directory. The functions 61 | look for the package name and maintainer email address. Functions copy heavily from 62 | https://github.com/r-hub/rhub 63 | 64 | The functions 65 | 66 | - `cchn_register()`: registration 67 | - `cchn_pkg_rule_list()`/`cchn_rule_list()`: list your own rules 68 | - `cchn_pkg_rule_get()`/`cchn_rule_get()`: get a rule by id 69 | - `cchn_pkg_rule_add()`/`cchn_rule_add()`: create a rule 70 | - `cchn_pkg_rule_delete()`/`cchn_rule_delete()`: delete a rule by id (get id from `cchn_pkg_rule_list`/`cchn_rule_list`) 71 | 72 | Functions prefixed with `cchn_pkg_` operate within a package 73 | directory. That is, your current working directory is an R 74 | package, and is the package for which you want to handle CRAN checks 75 | notifications. These functions make sure that you are inside of 76 | an R package, and use the email address and package name based 77 | on the directory you're in. 78 | 79 | Functions prefixed with just `cchn_` do not operate within a package. 80 | These functions do not guess package name at all, but require the user 81 | to supply a package name (for those functions that require a package name); 82 | and instead of guessing an email address from your package, we guess email 83 | from the cached cchecks email file (see `?cchn_register`). 84 | 85 | The first thing to do is to register an email address. In an R session in a working directory for 86 | one of your packages that is on CRAN, run `cchn_register()`. This function: 87 | 88 | - registers your email address 89 | - a validation email is sent to you right away with your token 90 | - paste the token from the amil into the R session 91 | - the email and token are then saved in a file on your machine 92 | - all `cchn_rule*` functions use this cached token 93 | - you don't need to pass the token in any `cchn` function calls 94 | 95 | If you run `cchn_register()` in the same package directory (with the same email address), 96 | you'll be issued a new token, which will be updated in your cached token file. 97 | 98 | It's entirely possible to have more than one email address you use across different R packages. 99 | If you run `cchn_register()` in a different package directory (with a different email address 100 | from a previous run of `cchn_register()`), you'll be issued a different token associated 101 | with that new email address. 102 | 103 | See `?cchn_rules` for details on how the rules work and many examples of adding rules. 104 | 105 | Note that you can only manage your own rules. You can not list, get, or delete rules 106 | of other users. 107 | 108 | ## Meta 109 | 110 | * Please [report any issues or bugs](https://github.com/ropensci/cchecks/issues). 111 | * License: MIT 112 | * Get citation information for `cchecks` in R doing `citation(package = 'cchecks')` 113 | * Please note that this project is released with a [Contributor Code of Conduct][coc]. By participating in this project you agree to abide by its terms. 114 | 115 | [docs]: https://cranchecks.info/docs 116 | [coc]: https://github.com/ropensci/cchecks/blob/master/CODE_OF_CONDUCT.md 117 | -------------------------------------------------------------------------------- /README.Rmd: -------------------------------------------------------------------------------- 1 | cchecks 2 | ======= 3 | 4 | ```{r echo=FALSE} 5 | knitr::opts_chunk$set( 6 | warning = FALSE, 7 | message = FALSE, 8 | collapse = TRUE, 9 | comment = "#>" 10 | ) 11 | ``` 12 | 13 | [![R-CMD-check](https://github.com/ropensci/cchecks/workflows/R-CMD-check/badge.svg)](https://github.com/ropensci/cchecks/actions/) 14 | [![codecov.io](https://codecov.io/github/ropensci/cchecks/coverage.svg?branch=master)](https://codecov.io/github/ropensci/cchecks?branch=master) 15 | 16 | R client for the CRAN checks API at 17 | 18 | [CRAN checks API docs][docs] 19 | 20 | authentication is only needed for the CRAN checks API for the functions that start with `cchn` 21 | 22 | See https://docs.ropensci.org/cchecks for full documentation on `cchecks` 23 | 24 | ## Install 25 | 26 | ```{r eval=FALSE} 27 | remotes::install_github("ropensci/cchecks") 28 | ``` 29 | 30 | ```{r} 31 | library("cchecks") 32 | ``` 33 | 34 | ## heartbeat 35 | 36 | - `cch_heartbeat()` 37 | 38 | ## packages 39 | 40 | - current day package check data: `cch_pkgs()` or `cch_pkgs("packagename")` 41 | - historical package check data (30 days back): `cch_pkgs_history()` 42 | - historical package check data for all packages by day: `cch_history()` 43 | - search historical data: `cch_pkgs_search()` 44 | 45 | There's an important shortcoming of historical data. The links in the historical 46 | data in the `checks` field are not date specific. If you go to a link in historical 47 | data, for example for April 2nd, 2020, links in that set of data link to whatever 48 | the current check data is for that package. The `check_details` field is 49 | date specific though; the text is scraped from the package checks page each day 50 | and stored, so you can count on that to be date specific. There are sometimes 51 | links to further checks, often of compiled packages on various types of checks 52 | that CRAN runs; we do not have those check results - we could get them but 53 | have not take the time to sort that out. 54 | 55 | 56 | ## maintainers 57 | 58 | - all maintainers: `cch_maintainers()` 59 | - maintainers by email: `cch_maintainers("maelle.salmon_at_yahoo.se")` 60 | 61 | ## notifications 62 | 63 | Functions for working with notifications are all prefixed with `cchn`. 64 | 65 | `cchn` functions are designed to be used from within an R package directory. The functions 66 | look for the package name and maintainer email address. Functions copy heavily from 67 | https://github.com/r-hub/rhub 68 | 69 | The functions 70 | 71 | - `cchn_register()`: registration 72 | - `cchn_pkg_rule_list()`/`cchn_rule_list()`: list your own rules 73 | - `cchn_pkg_rule_get()`/`cchn_rule_get()`: get a rule by id 74 | - `cchn_pkg_rule_add()`/`cchn_rule_add()`: create a rule 75 | - `cchn_pkg_rule_delete()`/`cchn_rule_delete()`: delete a rule by id (get id from `cchn_pkg_rule_list`/`cchn_rule_list`) 76 | 77 | Functions prefixed with `cchn_pkg_` operate within a package 78 | directory. That is, your current working directory is an R 79 | package, and is the package for which you want to handle CRAN checks 80 | notifications. These functions make sure that you are inside of 81 | an R package, and use the email address and package name based 82 | on the directory you're in. 83 | 84 | Functions prefixed with just `cchn_` do not operate within a package. 85 | These functions do not guess package name at all, but require the user 86 | to supply a package name (for those functions that require a package name); 87 | and instead of guessing an email address from your package, we guess email 88 | from the cached cchecks email file (see `?cchn_register`). 89 | 90 | The first thing to do is to register an email address. In an R session in a working directory for 91 | one of your packages that is on CRAN, run `cchn_register()`. This function: 92 | 93 | - registers your email address 94 | - a validation email is sent to you right away with your token 95 | - paste the token from the amil into the R session 96 | - the email and token are then saved in a file on your machine 97 | - all `cchn_rule*` functions use this cached token 98 | - you don't need to pass the token in any `cchn` function calls 99 | 100 | If you run `cchn_register()` in the same package directory (with the same email address), 101 | you'll be issued a new token, which will be updated in your cached token file. 102 | 103 | It's entirely possible to have more than one email address you use across different R packages. 104 | If you run `cchn_register()` in a different package directory (with a different email address 105 | from a previous run of `cchn_register()`), you'll be issued a different token associated 106 | with that new email address. 107 | 108 | See `?cchn_rules` for details on how the rules work and many examples of adding rules. 109 | 110 | Note that you can only manage your own rules. You can not list, get, or delete rules 111 | of other users. 112 | 113 | ## Meta 114 | 115 | * Please [report any issues or bugs](https://github.com/ropensci/cchecks/issues). 116 | * License: MIT 117 | * Get citation information for `cchecks` in R doing `citation(package = 'cchecks')` 118 | * Please note that this project is released with a [Contributor Code of Conduct][coc]. By participating in this project you agree to abide by its terms. 119 | 120 | [docs]: https://cranchecks.info/docs 121 | [coc]: https://github.com/ropensci/cchecks/blob/master/CODE_OF_CONDUCT.md 122 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Project Status: Abandoned](https://www.repostatus.org/badges/latest/abandoned.svg)](https://www.repostatus.org/#abandoned) 2 | 3 | This package has been archived. The former README is now in [README-not](README-not.md). 4 | -------------------------------------------------------------------------------- /cchecks.Rproj: -------------------------------------------------------------------------------- 1 | Version: 1.0 2 | 3 | RestoreWorkspace: Default 4 | SaveWorkspace: Default 5 | AlwaysSaveHistory: Default 6 | 7 | EnableCodeIndexing: Yes 8 | UseSpacesForTab: Yes 9 | NumSpacesForTab: 2 10 | Encoding: UTF-8 11 | 12 | RnwWeave: Sweave 13 | LaTeX: pdfLaTeX 14 | 15 | BuildType: Package 16 | PackageUseDevtools: Yes 17 | PackageInstallArgs: --no-multiarch --with-keep.source 18 | -------------------------------------------------------------------------------- /man/cch_heartbeat.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/cch_heartbeat.R 3 | \name{cch_heartbeat} 4 | \alias{cch_heartbeat} 5 | \title{Get heartbeat} 6 | \usage{ 7 | cch_heartbeat(...) 8 | } 9 | \arguments{ 10 | \item{...}{Curl options passed to \code{\link[crul:HttpClient]{crul::HttpClient()}}} 11 | } 12 | \value{ 13 | list of routes 14 | } 15 | \description{ 16 | Get heartbeat 17 | } 18 | \examples{ 19 | \dontrun{ 20 | cch_heartbeat() 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /man/cch_history.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/cch_history.R 3 | \name{cch_history} 4 | \alias{cch_history} 5 | \title{Get historical check data for all packages by date} 6 | \usage{ 7 | cch_history(date, ...) 8 | } 9 | \arguments{ 10 | \item{date}{(character) a date of the form \code{YYYY-MM-DD}. required} 11 | 12 | \item{...}{Curl options passed to \link[crul:verb-GET]{crul::verb-GET}} 13 | } 14 | \value{ 15 | a tibble with columns: 16 | \itemize{ 17 | \item package: character vector of package names 18 | \item summary: character vector of JSON hash's of check summary data 19 | \item checks: character vector of JSON hash's of checks performed 20 | \item check_details: character vector of check details. if no check 21 | details the string will be "null"; if details given, then 22 | a JSON hash of details 23 | \item date_updated: character vector of dates, the date the check was 24 | performed on 25 | } 26 | } 27 | \description{ 28 | Get historical check data for all packages by date 29 | } 30 | \details{ 31 | This function gets historical data for all packages for a single 32 | day; see \code{\link[=cch_pkgs_history]{cch_pkgs_history()}} for last 30 days history for particular 33 | packages 34 | 35 | You have to do a bit of data wrangling to get this data into a 36 | easily sortable/filterable/etc. form 37 | } 38 | \examples{ 39 | \dontrun{ 40 | x <- cch_history(date = "2020-04-01") 41 | str(x) 42 | lapply(x$summary[1:3], jsonlite::fromJSON) 43 | } 44 | } 45 | \seealso{ 46 | \code{\link[=cch_pkgs_history]{cch_pkgs_history()}} 47 | } 48 | -------------------------------------------------------------------------------- /man/cch_maintainers.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/cch_maintainers.R 3 | \name{cch_maintainers} 4 | \alias{cch_maintainers} 5 | \title{Get maintainer based checks} 6 | \usage{ 7 | cch_maintainers(x = NULL, limit = 10, offset = 0, ...) 8 | } 9 | \arguments{ 10 | \item{x}{email slug name, optional, if you pass in more than one 11 | we'll do async} 12 | 13 | \item{limit}{number of records to return. Default: 10} 14 | 15 | \item{offset}{record number to start at. Default: 0} 16 | 17 | \item{...}{Curl options passed to \code{\link[crul:HttpClient]{crul::HttpClient()}} or 18 | \code{\link[crul:Async]{crul::Async()}}} 19 | } 20 | \value{ 21 | list of info about a package(s) 22 | } 23 | \description{ 24 | Get maintainer based checks 25 | } 26 | \examples{ 27 | \dontrun{ 28 | x <- cch_maintainers() 29 | x$data 30 | x$data$summary 31 | x$data$checks 32 | x$data$date_updated 33 | x$data$package 34 | x$data$url 35 | 36 | cch_maintainers("00gerhard_at_gmail.com") 37 | cch_maintainers(c("123saga_at_gmail.com", "13268259225_at_163.com", 38 | "csardi.gabor_at_gmail.com")) 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /man/cch_pkgs.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/cch_pkgs.R 3 | \name{cch_pkgs} 4 | \alias{cch_pkgs} 5 | \title{Get package checks data} 6 | \usage{ 7 | cch_pkgs(x = NULL, limit = 10, offset = 0, ...) 8 | } 9 | \arguments{ 10 | \item{x}{package name, optional, if you pass in more than one 11 | we'll do async} 12 | 13 | \item{limit}{number of records to return. Default: 10} 14 | 15 | \item{offset}{record number to start at. Default: 0} 16 | 17 | \item{...}{Curl options passed to \code{\link[crul:HttpClient]{crul::HttpClient()}} or 18 | \code{\link[crul:Async]{crul::Async()}}} 19 | } 20 | \value{ 21 | list of info about a package(s) 22 | } 23 | \description{ 24 | Get package checks data 25 | } 26 | \note{ 27 | this function only gets the current days checks; see 28 | \code{\link[=cch_pkgs_history]{cch_pkgs_history()}} for historical data 29 | } 30 | \examples{ 31 | \dontrun{ 32 | x <- cch_pkgs() 33 | x$data 34 | x$data$summary 35 | x$data$checks 36 | x$data$date_updated 37 | x$data$package 38 | x$data$url 39 | 40 | cch_pkgs("geojsonio") 41 | cch_pkgs(c("geojsonio", "leaflet", "MASS")) 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /man/cch_pkgs_history.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/cch_pkgs_history.R 3 | \name{cch_pkgs_history} 4 | \alias{cch_pkgs_history} 5 | \title{Get historical check data for packages} 6 | \usage{ 7 | cch_pkgs_history(x, limit = 30, offset = 0, ...) 8 | } 9 | \arguments{ 10 | \item{x}{package name, required, if you pass in more than one 11 | we'll do async} 12 | 13 | \item{limit}{number of records to return. Default: 10} 14 | 15 | \item{offset}{record number to start at. Default: 0} 16 | 17 | \item{...}{Curl options passed to \code{\link[crul:HttpClient]{crul::HttpClient()}} or 18 | \code{\link[crul:Async]{crul::Async()}}} 19 | } 20 | \value{ 21 | list of info about a package(s) 22 | } 23 | \description{ 24 | Get historical check data for packages 25 | } 26 | \details{ 27 | this function gets historical data; for current day check data only 28 | see \code{\link[=cch_pkgs]{cch_pkgs()}} 29 | 30 | data is only available for 30 days prior to today's date, see the 31 | \code{\link[=cch_history]{cch_history()}} function for older data 32 | } 33 | \examples{ 34 | \dontrun{ 35 | x <- cch_pkgs_history(x = "geojsonio") 36 | x 37 | x$data 38 | x$data$package 39 | x$data$history 40 | x$data$history$summary 41 | x$data$history$summary$any 42 | x$data$history$check_details 43 | 44 | # many packages 45 | res <- cch_pkgs_history(c("geojsonio", "leaflet", "MASS")) 46 | res 47 | 48 | # pagination 49 | cch_pkgs_history(x = "geojsonio", limit = 3) 50 | cch_pkgs_history(x = "geojsonio", limit = 3, offset = 4) 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /man/cch_pkgs_search.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/cch_pkgs_search.R 3 | \name{cch_pkgs_search} 4 | \alias{cch_pkgs_search} 5 | \title{Search historical package check data} 6 | \usage{ 7 | cch_pkgs_search( 8 | q, 9 | package = NULL, 10 | one_each = FALSE, 11 | fields = NULL, 12 | limit = 30, 13 | offset = 0, 14 | ... 15 | ) 16 | } 17 | \arguments{ 18 | \item{q}{(character) full text query string} 19 | 20 | \item{package}{(character) a package name. limit results to a single 21 | package, e.g, \code{package="taxize"}} 22 | 23 | \item{one_each}{(logical) if \code{TRUE}, return a single result for each package; 24 | useful if you want to find out what packages match a particular query, and 25 | don't care which day that match happened. default: \code{FALSE}} 26 | 27 | \item{fields}{(character) vector of fields to return, e.g., 28 | \code{fields=c("package", "check_details")}} 29 | 30 | \item{limit}{number of records to return. Default: 10} 31 | 32 | \item{offset}{record number to start at. Default: 0} 33 | 34 | \item{...}{Curl options passed to \code{\link[crul:HttpClient]{crul::HttpClient()}} or 35 | \code{\link[crul:Async]{crul::Async()}}} 36 | } 37 | \value{ 38 | list of info about a package(s) 39 | } 40 | \description{ 41 | Search historical package check data 42 | } 43 | \examples{ 44 | \dontrun{ 45 | x <- cch_pkgs_search(q = "memory") 46 | x 47 | x$data 48 | x$data$package 49 | x$data 50 | x$data$summary 51 | x$data$summary$any 52 | x$data$check_details 53 | 54 | # restrict returned fields 55 | res <- cch_pkgs_search("memory", fields = c("package", "check_details")) 56 | res$data$check_details$output[1] 57 | grepl('memory', res$data$check_details$output[1]) 58 | 59 | # one each, one record per package 60 | res <- cch_pkgs_search("memory", one_each = TRUE, 61 | fields = c("package", "date_updated")) 62 | res 63 | 64 | # pagination 65 | cch_pkgs_search("memory", limit = 3) 66 | cch_pkgs_search("memory", limit = 3, offset = 4) 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /man/cchecks-package.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/cchecks-package.R 3 | \docType{package} 4 | \name{cchecks-package} 5 | \alias{cchecks-package} 6 | \alias{cchecks} 7 | \title{cchecks} 8 | \description{ 9 | Client for the cranchecks.info API 10 | } 11 | \section{Docs}{ 12 | 13 | See \url{https://cranchecks.info/docs} 14 | } 15 | 16 | \section{Historical data}{ 17 | 18 | There's an important shortcoming of historical data. The links in the 19 | historical data in the \code{checks} field are not date specific. If you go to a 20 | link in historical data, for example for April 2nd, 2020, links in that set 21 | of data link to whatever the current check data is for that package. The 22 | \code{check_details} field is date specific though; the text is scraped from the 23 | package checks page each day and stored, so you can count on that to be date 24 | specific. There are sometimes links to further checks, often of compiled 25 | packages on various types of checks that CRAN runs; we do not have those 26 | check results - we could get them but have not take the time to sort that 27 | out. 28 | } 29 | 30 | \author{ 31 | Scott Chamberlain \email{sckott@protonmail.com} 32 | } 33 | \keyword{package} 34 | -------------------------------------------------------------------------------- /man/cchn_register.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/cchn_register.R 3 | \name{cchn_register} 4 | \alias{cchn_register} 5 | \title{Notifications: register your email address and get a token} 6 | \usage{ 7 | cchn_register(email = NULL, token = NULL, ...) 8 | } 9 | \arguments{ 10 | \item{email}{(character) email address to use for interaction with 11 | the CRAN checks API. If no email address is given, we go through a few 12 | steps: check for the cached file mentioned below for any emails; use 13 | \code{\link[whoami:email_address]{whoami::email_address()}}; if the location you are running this in is 14 | a package, we look for the maintainer's email address in the package.} 15 | 16 | \item{token}{(character) your CRAN checks API token. you shouldn't need 17 | to pass a token here. if you used \code{\link[=cchn_register]{cchn_register()}} your token should 18 | be cached} 19 | 20 | \item{...}{Curl options passed to \link[crul:verb-GET]{crul::verb-GET}} 21 | } 22 | \value{ 23 | \code{NULL} - nothing returned 24 | } 25 | \description{ 26 | Notifications: register your email address and get a token 27 | } 28 | \details{ 29 | We cache a file with email addresses and tokens at the path 30 | \code{file.path(rappdirs::user_data_dir("cranchecks", "cchecks"), "emails.csv")} 31 | You can run that in R to get the path for the file on your machine. 32 | 33 | To get a new token for an email address that was previously registered, 34 | go to the file above and delete the line with the email address and token 35 | for the email address in question; remember to save the change. 36 | Then when you run \code{cchn_register()} again for that email you can get 37 | a new token. 38 | 39 | To add an email address that was validated before (probably on 40 | another machine), to the configuration file, call this function 41 | with the ‘email’ and ‘token’ arguments. 42 | } 43 | -------------------------------------------------------------------------------- /man/cchn_rules.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/cchn_rules.R, R/rule-add.R, R/rule-delete.R, 3 | % R/rule-get.R, R/rule-list.R 4 | \name{cchn_rules} 5 | \alias{cchn_rules} 6 | \alias{cchn_rules_add} 7 | \alias{cchn_pkg_rule_add} 8 | \alias{cchn_rule_add} 9 | \alias{cchn_pkg_rule_delete} 10 | \alias{cchn_rule_delete} 11 | \alias{cchn_pkg_rule_get} 12 | \alias{cchn_rule_get} 13 | \alias{cchn_pkg_rule_list} 14 | \alias{cchn_rule_list} 15 | \title{Notifications: add, list, get, delete notification rules} 16 | \usage{ 17 | cchn_rules_add(rules, email, quiet = FALSE, ...) 18 | 19 | cchn_pkg_rule_add( 20 | status = NULL, 21 | platform = NULL, 22 | time = NULL, 23 | regex = NULL, 24 | package = NULL, 25 | email = NULL, 26 | path = ".", 27 | quiet = FALSE, 28 | ... 29 | ) 30 | 31 | cchn_rule_add( 32 | package, 33 | status = NULL, 34 | platform = NULL, 35 | time = NULL, 36 | regex = NULL, 37 | email = NULL, 38 | quiet = FALSE, 39 | ... 40 | ) 41 | 42 | cchn_pkg_rule_delete(id, email = NULL, path = ".", ...) 43 | 44 | cchn_rule_delete(id, email = NULL, quiet = FALSE, ...) 45 | 46 | cchn_pkg_rule_get(id, email = NULL, path = ".", ...) 47 | 48 | cchn_rule_get(id, email = NULL, quiet = FALSE, ...) 49 | 50 | cchn_pkg_rule_list(email = NULL, path = ".", ...) 51 | 52 | cchn_rule_list(email = NULL, quiet = FALSE, ...) 53 | } 54 | \arguments{ 55 | \item{rules}{(list) a list of rules. each element in the list must 56 | be a named list, in which each must have a "package", and a set of 57 | rules (see below)} 58 | 59 | \item{email}{(character) email address to use for interaction with 60 | the CRAN checks API. we use the email address in the maintainers slot 61 | of the DESCRIPTION file of your working directory. you can supply an 62 | email address instead} 63 | 64 | \item{quiet}{(logical) suppress messages? default: \code{FALSE}} 65 | 66 | \item{...}{Curl options passed to \link[crul:verb-GET]{crul::verb-GET}, \link[crul:verb-POST]{crul::verb-POST}, or 67 | \link[crul:verb-DELETE]{crul::verb-DELETE}} 68 | 69 | \item{status}{(character) a check status, one of: error, warn, note, fail} 70 | 71 | \item{platform}{(character) a platform, a string to match against the 72 | platform strings used by cran checks. e.g., "osx" would match any osx 73 | platform check results, whereas you could limit the rule to just a single 74 | specific platform by using the target platforms exact string 75 | "r-oldrel-osx-x86_64". Leave as \code{NULL} (the default) to match all 76 | platforms.} 77 | 78 | \item{time}{(integer) number of days} 79 | 80 | \item{regex}{(character) a regex string} 81 | 82 | \item{package}{(character) a package name. if \code{NULL}, we attempt to 83 | get the package name from the working directory, and fail out if there's 84 | not a valid package structure/package name} 85 | 86 | \item{path}{(character) path to a directory containing an R package} 87 | 88 | \item{id}{(integer) a rule id. note that you can not get or delete 89 | rules that are not yours. required} 90 | } 91 | \value{ 92 | \itemize{ 93 | \item \code{cchn_pkg_rule_add()}/\code{cchn_rule_add()}/\code{cchn_rules_add()}: message about 94 | the rule added, and a note about using \code{cchn_rule_list()} to list your rules 95 | \item \code{cchn_pkg_rule_get()}/\code{cchn_rule_get()}: list with elements \code{error} and 96 | \code{data} (a list of the parts of the rule) 97 | \item \code{cchn_pkg_rule_list()}/\code{cchn_rule_list()}: list with elements \code{error} and 98 | \code{data} (a data.frame of all the rules associated with your email) 99 | \item \code{cchn_pkg_rule_delete()}/\code{cchn_rule_delete()}: if deletion works, a 100 | message saying "ok" 101 | } 102 | } 103 | \description{ 104 | Notifications: add, list, get, delete notification rules 105 | } 106 | \details{ 107 | Functions prefixed with \code{cchn_pkg_} operate within a package 108 | directory. That is, your current working directory is an R 109 | package, and is the package for which you want to handle CRAN checks 110 | notifications. These functions make sure that you are inside of 111 | an R package, and use the email address and package name based 112 | on the directory you're in. 113 | 114 | Functions prefixed with just \code{cchn_} do not operate within a package. 115 | These functions do not guess package name at all, but require the user 116 | to supply a package name (for those functions that require a package name); 117 | and instead of guessing an email address from your package, we guess email 118 | from the cached cchecks email file. 119 | \itemize{ 120 | \item \code{cchn_pkg_rule_add()}/\code{cchn_rule_add()}: add a rule, one rule per 121 | function call 122 | \item \code{cchn_rules_add()}: add many rules at once; no option for package context 123 | \item \code{cchn_pkg_rule_get()}/\code{cchn_rule_get()}: get a rule by rule id (see 124 | \code{cchn_pkg_rule_list()}/\code{cchn_rule_list()} to get ids; can only get rules for 125 | the authenticated user) 126 | \item \code{cchn_pkg_rule_list()}/\code{cchn_rule_list()}: list rules for the 127 | authenticated user - \code{cchn_pkg_rule_list()} lists rules only for the package 128 | in question, while \code{cchn_rule_list()} lists all rules for the user (email) 129 | \item \code{cchn_pkg_rule_delete()}/\code{cchn_rule_delete()}: delete a rule by rule id 130 | (only those for the authenticated user) 131 | } 132 | } 133 | \section{example rules}{ 134 | 135 | 136 | Note that the first parameter \code{package} is left out for brevity 137 | \itemize{ 138 | \item ERROR for at least 1 day across all platforms 139 | \itemize{ 140 | \item \code{cchn_rule_add(status = 'error')} 141 | } 142 | \item ERROR for 3 days in a row across 2 or more platforms 143 | \itemize{ 144 | \item \code{cchn_rule_add(status = 'error', time = 3, platform = 2)} 145 | } 146 | \item ERROR for 2 days in a row on all osx platforms 147 | \itemize{ 148 | \item \code{cchn_rule_add(status = 'error', time = 2, platform = "osx")} 149 | } 150 | \item ERROR for 2 days in a row on all release R versions 151 | \itemize{ 152 | \item \code{cchn_rule_add(status = 'error', time = 2, platform = "release")} 153 | } 154 | \item WARN for 4 days in a row on any platform except Solaris 155 | \itemize{ 156 | \item \code{cchn_rule_add(status = 'warn', time = 4, platform = "-solaris")} 157 | } 158 | \item WARN for 2 days in a row across 9 or more platforms 159 | \itemize{ 160 | \item \code{cchn_rule_add(status = 'warn', time = 2, platform = 10)} 161 | } 162 | \item NOTE on any osx platform 163 | \itemize{ 164 | \item \code{cchn_rule_add(status = 'note', platform = "osx")} 165 | } 166 | \item NOTE on any platform 167 | \itemize{ 168 | \item \code{cchn_rule_add(status = 'note')} 169 | } 170 | \item error details contain regex 'install' 171 | \itemize{ 172 | \item \code{cchn_rule_add(regex = "install")} 173 | } 174 | } 175 | } 176 | 177 | \examples{ 178 | \dontrun{ 179 | ## Workflow 1: within a package directory 180 | # (x <- cchn_pkg_rule_list()) 181 | # if (length(x$data$id) > 0) { 182 | # cchn_pkg_rule_get(x$data$id[1]) 183 | # cchn_pkg_rule_delete(x$data$id[1]) 184 | # cchn_pkg_rule_get(id = x$data$id[1]) 185 | # } 186 | 187 | ## Workflow 2: not in a package directory 188 | # (x <- cchn_rule_list()) 189 | # if (length(x$data$id) > 0) { 190 | # cchn_rule_get(x$data$id[1]) 191 | # cchn_rule_delete(x$data$id[1]) 192 | # cchn_rule_get(id = x$data$id[1]) 193 | # } 194 | 195 | ## cchn_pkg_rule_add: add a rule - guesses the package name 196 | ## you can specify the package name instead 197 | # cchn_pkg_rule_add(status = "note", platform = 3, 198 | # email = "some-email") 199 | ## cchn_rule_add: add a rule - not in package context, must 200 | ## specify the package name 201 | # cchn_rule_add(package = "foobar", status = "note", platform = 3, 202 | # email = "some-email") 203 | 204 | ## cchn_pkg_rule_add: should guess package name and email 205 | # cchn_pkg_rule_add(status = "note", platform = 3) 206 | 207 | ## cchn_rule_add: package name must be supplied. takes first email 208 | ## from cached emails.csv file, see `?cchn_register` for more 209 | # cchn_rule_add(package = "foobar", status = "warn", platform = 2) 210 | 211 | ## cchn_rules_add: add many rules at once 212 | ## no package context here, email and package names must be given 213 | # pkg <- "charlatan" 214 | # rules <- list( 215 | # list(package = pkg, status = "warn"), 216 | # list(package = pkg, status = "error", time = 4) 217 | # ) 218 | # cchn_rules_add(rules, "your-email", verbose = TRUE) 219 | } 220 | } 221 | -------------------------------------------------------------------------------- /tests/fixtures/cch_heartbeat.yml: -------------------------------------------------------------------------------- 1 | http_interactions: 2 | - request: 3 | method: get 4 | uri: https://cranchecks.info/heartbeat 5 | body: 6 | encoding: '' 7 | string: '' 8 | headers: 9 | User-Agent: r-curl/4.3 crul/0.9.0 rOpenSci(cchecks/0.1.5.91) 10 | Accept-Encoding: gzip, deflate 11 | Accept: application/json, text/xml, application/xml, */* 12 | Authorization: 'Bearer ' 13 | response: 14 | status: 15 | status_code: '200' 16 | message: OK 17 | explanation: Request fulfilled, document follows 18 | headers: 19 | status: 'HTTP/2 200 ' 20 | access-control-allow-methods: HEAD, GET 21 | access-control-allow-origin: '*' 22 | cache-control: public, must-revalidate, max-age=60 23 | content-encoding: gzip 24 | content-type: application/json; charset=utf8 25 | server: Caddy 26 | vary: Accept-Encoding 27 | x-content-type-options: nosniff 28 | content-length: '159' 29 | date: Mon, 11 May 2020 23:32:11 GMT 30 | body: 31 | encoding: UTF-8 32 | file: no 33 | string: '{"routes":["/","/docs","/heartbeat/?","/pkgs","/pkgs/:name","/maintainers","/maintainers/:email","/badges/:type/:package","/badges/flavor/:flavor/:package","/pkgs/:name/history","/history/:date","/notifications/rules","/notifications/rules/:id"]}' 34 | recorded_at: 2020-05-11 23:32:11 GMT 35 | recorded_with: vcr/0.5.4, webmockr/0.6.2.92 36 | -------------------------------------------------------------------------------- /tests/fixtures/cch_history_error.yml: -------------------------------------------------------------------------------- 1 | http_interactions: 2 | - request: 3 | method: get 4 | uri: https://cranchecks.info/history/2030-05-22 5 | body: 6 | encoding: '' 7 | string: '' 8 | headers: 9 | User-Agent: r-curl/4.3 crul/0.9.0 rOpenSci(cchecks/0.1.8.91) 10 | Accept-Encoding: gzip, deflate 11 | Accept: application/json, text/xml, application/xml, */* 12 | response: 13 | status: 14 | status_code: '404' 15 | message: Not Found 16 | explanation: Nothing matches the given URI 17 | headers: 18 | status: HTTP/1.1 404 Not Found 19 | x-amz-request-id: 509F1E592412A8B3 20 | x-amz-id-2: Xb4AN1IyjZBfi+Q0CigSg2XqvshHwXoBrlk/ej2tdpYWyVjxB/XwG67eRWGHva5sTj/xfBj2sDI= 21 | content-type: application/xml 22 | transfer-encoding: chunked 23 | date: Fri, 22 May 2020 17:17:07 GMT 24 | server: AmazonS3 25 | body: 26 | encoding: UTF-8 27 | file: no 28 | string: |- 29 | 30 | NoSuchKeyThe specified key does not exist.2030-05-22.json.gz509F1E592412A8B3Xb4AN1IyjZBfi+Q0CigSg2XqvshHwXoBrlk/ej2tdpYWyVjxB/XwG67eRWGHva5sTj/xfBj2sDI= 31 | recorded_at: 2020-05-22 17:17:08 GMT 32 | recorded_with: vcr/0.5.4, webmockr/0.6.2 33 | -------------------------------------------------------------------------------- /tests/fixtures/cch_maintainers_all_maints.yml: -------------------------------------------------------------------------------- 1 | http_interactions: 2 | - request: 3 | method: get 4 | uri: https://cranchecks.info/maintainers?limit=10&offset=0 5 | body: 6 | encoding: '' 7 | string: '' 8 | headers: 9 | User-Agent: r-curl/4.3 crul/0.9.0 rOpenSci(cchecks/0.1.5.91) 10 | Accept-Encoding: gzip, deflate 11 | Accept: application/json, text/xml, application/xml, */* 12 | Authorization: 'Bearer ' 13 | response: 14 | status: 15 | status_code: '200' 16 | message: OK 17 | explanation: Request fulfilled, document follows 18 | headers: 19 | status: 'HTTP/2 200 ' 20 | access-control-allow-methods: HEAD, GET 21 | access-control-allow-origin: '*' 22 | cache-control: public, must-revalidate, max-age=60 23 | content-encoding: gzip 24 | content-type: application/json; charset=utf8 25 | server: Caddy 26 | vary: Accept-Encoding 27 | x-content-type-options: nosniff 28 | content-length: '1004' 29 | date: Mon, 11 May 2020 23:36:40 GMT 30 | body: 31 | encoding: UTF-8 32 | file: no 33 | string: '{"found":9411,"count":10,"offset":0,"error":null,"data":[{"_id":"f.briatte_at_gmail.com","email":"f.briatte_at_gmail.com","name":"François Briatte","url":"https://cloud.r-project.org/web/checks/check_results_f.briatte_at_gmail.com.html","table":[{"package":"ggnetwork","any":true,"ok":7,"note":5,"warn":0,"error":0}],"packages":[{"package":"ggnetwork","url":"https://cloud.r-project.org/web/checks/check_results_ggnetwork.html","check_result":[{"category":"NOTE","number_checks":5},{"category":"OK","number_checks":7}],"version":null}],"date_updated":"2020-05-11T20:00:50.651Z"},{"_id":"hyasrebi_at_yahoo.com","email":"hyasrebi_at_yahoo.com","name":"Haleh Yasrebi","url":"https://cloud.r-project.org/web/checks/check_results_hyasrebi_at_yahoo.com.html","table":[{"package":"survJamda","any":false,"ok":12,"note":0,"warn":0,"error":0},{"package":"survJamda.data","any":true,"ok":5,"note":7,"warn":0,"error":0}],"packages":[{"package":"survJamda","url":"https://cloud.r-project.org/web/checks/check_results_survJamda.html","check_result":[{"category":"OK","number_checks":12}],"version":null},{"package":"survJamda.data","url":"https://cloud.r-project.org/web/checks/check_results_survJamda.data.html","check_result":[{"category":"NOTE","number_checks":7},{"category":"OK","number_checks":5}],"version":null}],"date_updated":"2020-05-11T20:00:50.651Z"},{"_id":"ly_ding_at_126.com","email":"ly_ding_at_126.com","name":"Liuyong Ding","url":"https://cloud.r-project.org/web/checks/check_results_ly_ding_at_126.com.html","table":[{"package":"SP2000","any":false,"ok":12,"note":0,"warn":0,"error":0}],"packages":[{"package":"SP2000","url":"https://cloud.r-project.org/web/checks/check_results_SP2000.html","check_result":[],"version":null}],"date_updated":"2020-05-11T20:00:50.651Z"},{"_id":"bodri.mh3_at_gmail.com","email":"bodri.mh3_at_gmail.com","name":"Andras Bodor","url":"https://cloud.r-project.org/web/checks/check_results_bodri.mh3_at_gmail.com.html","table":[{"package":"rCUR","any":true,"ok":0,"note":5,"warn":0,"error":9}],"packages":[{"package":"rCUR","url":"https://cloud.r-project.org/web/checks/check_results_rCUR.html","check_result":[{"category":"ERROR","number_checks":9},{"category":"NOTE","number_checks":5}],"version":null}],"date_updated":"2020-05-11T20:00:50.651Z"},{"_id":"erich.neuwirth_at_univie.ac.at","email":"erich.neuwirth_at_univie.ac.at","name":"Erich Neuwirth","url":"https://cloud.r-project.org/web/checks/check_results_erich.neuwirth_at_univie.ac.at.html","table":[{"package":"ENmisc","any":true,"ok":0,"note":12,"warn":0,"error":0},{"package":"RcmdrPlugin.mosaic","any":true,"ok":0,"note":12,"warn":0,"error":0},{"package":"RColorBrewer","any":true,"ok":0,"note":12,"warn":0,"error":0}],"packages":[{"package":"ENmisc","url":"https://cloud.r-project.org/web/checks/check_results_ENmisc.html","check_result":[],"version":null},{"package":"RcmdrPlugin.mosaic","url":"https://cloud.r-project.org/web/checks/check_results_RcmdrPlugin.mosaic.html","check_result":[],"version":null},{"package":"RColorBrewer","url":"https://cloud.r-project.org/web/checks/check_results_RColorBrewer.html","check_result":[],"version":null}],"date_updated":"2020-05-11T20:00:50.651Z"},{"_id":"markus.boenn.sf_at_googlemail.com","email":"markus.boenn.sf_at_googlemail.com","name":"Markus Boenn","url":"https://cloud.r-project.org/web/checks/check_results_markus.boenn.sf_at_googlemail.com.html","table":[{"package":"hypergea","any":true,"ok":6,"note":6,"warn":0,"error":0}],"packages":[{"package":"hypergea","url":"https://cloud.r-project.org/web/checks/check_results_hypergea.html","check_result":[{"category":"NOTE","number_checks":6},{"category":"OK","number_checks":6}],"version":null}],"date_updated":"2020-05-11T20:00:50.651Z"},{"_id":"clement.benard_at_safrangroup.com","email":"clement.benard_at_safrangroup.com","name":"Clement Benard","url":"https://cloud.r-project.org/web/checks/check_results_clement.benard_at_safrangroup.com.html","table":[{"package":"sirus","any":true,"ok":9,"note":3,"warn":0,"error":0}],"packages":[{"package":"sirus","url":"https://cloud.r-project.org/web/checks/check_results_sirus.html","check_result":[{"category":"NOTE","number_checks":3},{"category":"OK","number_checks":9}],"version":null}],"date_updated":"2020-05-11T20:00:50.651Z"},{"_id":"s.greilich_at_dkfz.de","email":"s.greilich_at_dkfz.de","name":"Steffen Greilich","url":"https://cloud.r-project.org/web/checks/check_results_s.greilich_at_dkfz.de.html","table":[{"package":"libamtrack","any":true,"ok":2,"note":10,"warn":0,"error":0}],"packages":[{"package":"libamtrack","url":"https://cloud.r-project.org/web/checks/check_results_libamtrack.html","check_result":[{"category":"NOTE","number_checks":10},{"category":"OK","number_checks":2}],"version":null}],"date_updated":"2020-05-11T20:00:50.651Z"},{"_id":"eric_at_opsani.com","email":"eric_at_opsani.com","name":"Eric Kalosa-Kenyon","url":"https://cloud.r-project.org/web/checks/check_results_eric_at_opsani.com.html","table":[{"package":"soobench","any":true,"ok":11,"note":1,"warn":0,"error":0}],"packages":[{"package":"soobench","url":"https://cloud.r-project.org/web/checks/check_results_soobench.html","check_result":[{"category":"NOTE","number_checks":1},{"category":"OK","number_checks":11}],"version":null}],"date_updated":"2020-05-11T20:00:50.651Z"},{"_id":"egor_at_tillt.net","email":"egor_at_tillt.net","name":"Till Krenz","url":"https://cloud.r-project.org/web/checks/check_results_egor_at_tillt.net.html","table":[{"package":"egor","any":true,"ok":11,"note":0,"warn":0,"error":1}],"packages":[{"package":"egor","url":"https://cloud.r-project.org/web/checks/check_results_egor.html","check_result":[{"category":"ERROR","number_checks":1},{"category":"OK","number_checks":11}],"version":null}],"date_updated":"2020-05-11T20:00:50.651Z"}]}' 34 | recorded_at: 2020-05-11 23:36:41 GMT 35 | recorded_with: vcr/0.5.4, webmockr/0.6.2.92 36 | -------------------------------------------------------------------------------- /tests/fixtures/cch_maintainers_error.yml: -------------------------------------------------------------------------------- 1 | http_interactions: 2 | - request: 3 | method: get 4 | uri: https://cranchecks.info/maintainers?limit=foo&offset=0 5 | body: 6 | encoding: '' 7 | string: '' 8 | headers: 9 | User-Agent: r-curl/4.3 crul/0.9.0 rOpenSci(cchecks/0.1.5.91) 10 | Accept-Encoding: gzip, deflate 11 | Accept: application/json, text/xml, application/xml, */* 12 | Authorization: 'Bearer ' 13 | response: 14 | status: 15 | status_code: '400' 16 | message: Bad Request 17 | explanation: Bad request syntax or unsupported method 18 | headers: 19 | status: 'HTTP/2 400 ' 20 | access-control-allow-methods: HEAD, GET 21 | access-control-allow-origin: '*' 22 | cache-control: public, must-revalidate, max-age=60 23 | content-encoding: gzip 24 | content-type: application/json; charset=utf8 25 | server: Caddy 26 | vary: Accept-Encoding 27 | x-content-type-options: nosniff 28 | content-length: '86' 29 | date: Mon, 11 May 2020 23:36:40 GMT 30 | body: 31 | encoding: UTF-8 32 | file: no 33 | string: '{"count":0,"error":{"message":"limit is not an integer"},"data":null}' 34 | recorded_at: 2020-05-11 23:36:40 GMT 35 | recorded_with: vcr/0.5.4, webmockr/0.6.2.92 36 | - request: 37 | method: get 38 | uri: https://cranchecks.info/maintainers?limit=10&offset=bar 39 | body: 40 | encoding: '' 41 | string: '' 42 | headers: 43 | User-Agent: r-curl/4.3 crul/0.9.0 rOpenSci(cchecks/0.1.5.91) 44 | Accept-Encoding: gzip, deflate 45 | Accept: application/json, text/xml, application/xml, */* 46 | Authorization: 'Bearer ' 47 | response: 48 | status: 49 | status_code: '400' 50 | message: Bad Request 51 | explanation: Bad request syntax or unsupported method 52 | headers: 53 | status: 'HTTP/2 400 ' 54 | access-control-allow-methods: HEAD, GET 55 | access-control-allow-origin: '*' 56 | cache-control: public, must-revalidate, max-age=60 57 | content-encoding: gzip 58 | content-type: application/json; charset=utf8 59 | server: Caddy 60 | vary: Accept-Encoding 61 | x-content-type-options: nosniff 62 | content-length: '88' 63 | date: Mon, 11 May 2020 23:36:40 GMT 64 | body: 65 | encoding: UTF-8 66 | file: no 67 | string: '{"count":0,"error":{"message":"offset is not an integer"},"data":null}' 68 | recorded_at: 2020-05-11 23:36:40 GMT 69 | recorded_with: vcr/0.5.4, webmockr/0.6.2.92 70 | - request: 71 | method: get 72 | uri: https://cranchecks.info/maintainers/aaaaaaaaaaa?limit=10&offset=0 73 | body: 74 | encoding: '' 75 | string: '' 76 | headers: 77 | User-Agent: r-curl/4.3 crul/0.9.0 rOpenSci(cchecks/0.1.5.91) 78 | Accept-Encoding: gzip, deflate 79 | Accept: application/json, text/xml, application/xml, */* 80 | Authorization: 'Bearer ' 81 | response: 82 | status: 83 | status_code: '400' 84 | message: Bad Request 85 | explanation: Bad request syntax or unsupported method 86 | headers: 87 | status: 'HTTP/2 400 ' 88 | access-control-allow-methods: HEAD, GET 89 | access-control-allow-origin: '*' 90 | cache-control: public, must-revalidate, max-age=60 91 | content-encoding: gzip 92 | content-type: application/json; charset=utf8 93 | server: Caddy 94 | vary: Accept-Encoding 95 | x-content-type-options: nosniff 96 | content-length: '76' 97 | date: Mon, 11 May 2020 23:36:40 GMT 98 | body: 99 | encoding: UTF-8 100 | file: no 101 | string: '{"error":{"message":"no results found"},"data":null}' 102 | recorded_at: 2020-05-11 23:36:40 GMT 103 | recorded_with: vcr/0.5.4, webmockr/0.6.2.92 104 | -------------------------------------------------------------------------------- /tests/fixtures/cch_maintainers_one_maint.yml: -------------------------------------------------------------------------------- 1 | http_interactions: 2 | - request: 3 | method: get 4 | uri: https://cranchecks.info/maintainers/csardi.gabor_at_gmail.com?limit=10&offset=0 5 | body: 6 | encoding: '' 7 | string: '' 8 | headers: 9 | User-Agent: r-curl/4.3 crul/0.9.0 rOpenSci(cchecks/0.1.5.91) 10 | Accept-Encoding: gzip, deflate 11 | Accept: application/json, text/xml, application/xml, */* 12 | Authorization: 'Bearer ' 13 | response: 14 | status: 15 | status_code: '200' 16 | message: OK 17 | explanation: Request fulfilled, document follows 18 | headers: 19 | status: 'HTTP/2 200 ' 20 | access-control-allow-methods: HEAD, GET 21 | access-control-allow-origin: '*' 22 | cache-control: public, must-revalidate, max-age=60 23 | content-type: application/json; charset=utf8 24 | server: Caddy 25 | x-content-type-options: nosniff 26 | content-length: '12900' 27 | date: Mon, 11 May 2020 23:36:40 GMT 28 | body: 29 | encoding: UTF-8 30 | file: no 31 | string: '{"error":null,"data":{"_id":"csardi.gabor_at_gmail.com","email":"csardi.gabor_at_gmail.com","name":"Gábor Csárdi","url":"https://cloud.r-project.org/web/checks/check_results_csardi.gabor_at_gmail.com.html","table":[{"package":"asciicast","any":false,"ok":12,"note":0,"warn":0,"error":0},{"package":"callr","any":false,"ok":12,"note":0,"warn":0,"error":0},{"package":"cleancall","any":false,"ok":12,"note":0,"warn":0,"error":0},{"package":"cli","any":true,"ok":11,"note":0,"warn":1,"error":0},{"package":"cliapp","any":false,"ok":12,"note":0,"warn":0,"error":0},{"package":"clisymbols","any":false,"ok":12,"note":0,"warn":0,"error":0},{"package":"cranlike","any":false,"ok":12,"note":0,"warn":0,"error":0},{"package":"cranlogs","any":false,"ok":12,"note":0,"warn":0,"error":0},{"package":"crayon","any":true,"ok":11,"note":0,"warn":0,"error":1},{"package":"debugme","any":false,"ok":12,"note":0,"warn":0,"error":0},{"package":"desc","any":false,"ok":12,"note":0,"warn":0,"error":0},{"package":"disposables","any":false,"ok":12,"note":0,"warn":0,"error":0},{"package":"dotenv","any":false,"ok":12,"note":0,"warn":0,"error":0},{"package":"filelock","any":false,"ok":12,"note":0,"warn":0,"error":0},{"package":"franc","any":false,"ok":12,"note":0,"warn":0,"error":0},{"package":"gh","any":false,"ok":12,"note":0,"warn":0,"error":0},{"package":"igraph","any":true,"ok":5,"note":7,"warn":0,"error":0},{"package":"igraphdata","any":false,"ok":12,"note":0,"warn":0,"error":0},{"package":"isa2","any":false,"ok":12,"note":0,"warn":0,"error":0},{"package":"keypress","any":false,"ok":12,"note":0,"warn":0,"error":0},{"package":"keyring","any":true,"ok":10,"note":2,"warn":0,"error":0},{"package":"liteq","any":false,"ok":12,"note":0,"warn":0,"error":0},{"package":"lpSolve","any":false,"ok":12,"note":0,"warn":0,"error":0},{"package":"pak","any":true,"ok":11,"note":1,"warn":0,"error":0},{"package":"parsedate","any":false,"ok":12,"note":0,"warn":0,"error":0},{"package":"pingr","any":true,"ok":9,"note":0,"warn":0,"error":3},{"package":"pkgcache","any":false,"ok":12,"note":0,"warn":0,"error":0},{"package":"pkgconfig","any":false,"ok":12,"note":0,"warn":0,"error":0},{"package":"pkgsearch","any":false,"ok":12,"note":0,"warn":0,"error":0},{"package":"praise","any":false,"ok":12,"note":0,"warn":0,"error":0},{"package":"presser","any":true,"ok":11,"note":0,"warn":0,"error":1},{"package":"prettycode","any":false,"ok":12,"note":0,"warn":0,"error":0},{"package":"prettyunits","any":false,"ok":12,"note":0,"warn":0,"error":0},{"package":"processx","any":true,"ok":11,"note":0,"warn":1,"error":0},{"package":"progress","any":false,"ok":12,"note":0,"warn":0,"error":0},{"package":"ps","any":true,"ok":11,"note":0,"warn":0,"error":1},{"package":"rcmdcheck","any":false,"ok":12,"note":0,"warn":0,"error":0},{"package":"rcorpora","any":true,"ok":5,"note":7,"warn":0,"error":0},{"package":"rematch2","any":false,"ok":12,"note":0,"warn":0,"error":0},{"package":"rhub","any":false,"ok":12,"note":0,"warn":0,"error":0},{"package":"rversions","any":false,"ok":12,"note":0,"warn":0,"error":0},{"package":"sand","any":true,"ok":1,"note":11,"warn":0,"error":0},{"package":"sankey","any":false,"ok":12,"note":0,"warn":0,"error":0},{"package":"secret","any":false,"ok":12,"note":0,"warn":0,"error":0},{"package":"sessioninfo","any":false,"ok":12,"note":0,"warn":0,"error":0},{"package":"showimage","any":false,"ok":12,"note":0,"warn":0,"error":0},{"package":"tracer","any":false,"ok":12,"note":0,"warn":0,"error":0},{"package":"webdriver","any":false,"ok":12,"note":0,"warn":0,"error":0},{"package":"whoami","any":false,"ok":12,"note":0,"warn":0,"error":0},{"package":"xmlparsedata","any":false,"ok":12,"note":0,"warn":0,"error":0},{"package":"xopen","any":false,"ok":12,"note":0,"warn":0,"error":0},{"package":"zip","any":false,"ok":12,"note":0,"warn":0,"error":0}],"packages":[{"package":"asciicast","url":"https://cloud.r-project.org/web/checks/check_results_asciicast.html","check_result":[{"category":"OK","number_checks":12}],"version":null},{"package":"callr","url":"https://cloud.r-project.org/web/checks/check_results_callr.html","check_result":[{"category":"OK","number_checks":12}],"version":null},{"package":"cleancall","url":"https://cloud.r-project.org/web/checks/check_results_cleancall.html","check_result":[{"category":"OK","number_checks":12}],"version":null},{"package":"cli","url":"https://cloud.r-project.org/web/checks/check_results_cli.html","check_result":[{"category":"WARN","number_checks":1},{"category":"OK","number_checks":11}],"version":null},{"package":"cliapp","url":"https://cloud.r-project.org/web/checks/check_results_cliapp.html","check_result":[{"category":"OK","number_checks":12}],"version":null},{"package":"clisymbols","url":"https://cloud.r-project.org/web/checks/check_results_clisymbols.html","check_result":[{"category":"OK","number_checks":12}],"version":null},{"package":"cranlike","url":"https://cloud.r-project.org/web/checks/check_results_cranlike.html","check_result":[{"category":"OK","number_checks":12}],"version":null},{"package":"cranlogs","url":"https://cloud.r-project.org/web/checks/check_results_cranlogs.html","check_result":[{"category":"OK","number_checks":12}],"version":null},{"package":"crayon","url":"https://cloud.r-project.org/web/checks/check_results_crayon.html","check_result":[{"category":"ERROR","number_checks":1},{"category":"OK","number_checks":11}],"version":null},{"package":"debugme","url":"https://cloud.r-project.org/web/checks/check_results_debugme.html","check_result":[{"category":"OK","number_checks":12}],"version":null},{"package":"desc","url":"https://cloud.r-project.org/web/checks/check_results_desc.html","check_result":[{"category":"OK","number_checks":12}],"version":null},{"package":"disposables","url":"https://cloud.r-project.org/web/checks/check_results_disposables.html","check_result":[{"category":"OK","number_checks":12}],"version":null},{"package":"dotenv","url":"https://cloud.r-project.org/web/checks/check_results_dotenv.html","check_result":[{"category":"OK","number_checks":12}],"version":null},{"package":"filelock","url":"https://cloud.r-project.org/web/checks/check_results_filelock.html","check_result":[{"category":"OK","number_checks":12}],"version":null},{"package":"franc","url":"https://cloud.r-project.org/web/checks/check_results_franc.html","check_result":[{"category":"OK","number_checks":12}],"version":null},{"package":"gh","url":"https://cloud.r-project.org/web/checks/check_results_gh.html","check_result":[{"category":"OK","number_checks":12}],"version":null},{"package":"igraph","url":"https://cloud.r-project.org/web/checks/check_results_igraph.html","check_result":[{"category":"NOTE","number_checks":7},{"category":"OK","number_checks":5}],"version":null},{"package":"igraphdata","url":"https://cloud.r-project.org/web/checks/check_results_igraphdata.html","check_result":[{"category":"OK","number_checks":12}],"version":null},{"package":"isa2","url":"https://cloud.r-project.org/web/checks/check_results_isa2.html","check_result":[{"category":"OK","number_checks":12}],"version":null},{"package":"keypress","url":"https://cloud.r-project.org/web/checks/check_results_keypress.html","check_result":[{"category":"OK","number_checks":12}],"version":null},{"package":"keyring","url":"https://cloud.r-project.org/web/checks/check_results_keyring.html","check_result":[{"category":"NOTE","number_checks":2},{"category":"OK","number_checks":10}],"version":null},{"package":"liteq","url":"https://cloud.r-project.org/web/checks/check_results_liteq.html","check_result":[{"category":"OK","number_checks":12}],"version":null},{"package":"lpSolve","url":"https://cloud.r-project.org/web/checks/check_results_lpSolve.html","check_result":[{"category":"OK","number_checks":12}],"version":null},{"package":"pak","url":"https://cloud.r-project.org/web/checks/check_results_pak.html","check_result":[{"category":"NOTE","number_checks":1},{"category":"OK","number_checks":11}],"version":null},{"package":"parsedate","url":"https://cloud.r-project.org/web/checks/check_results_parsedate.html","check_result":[{"category":"OK","number_checks":12}],"version":null},{"package":"pingr","url":"https://cloud.r-project.org/web/checks/check_results_pingr.html","check_result":[{"category":"ERROR","number_checks":3},{"category":"OK","number_checks":9}],"version":null},{"package":"pkgcache","url":"https://cloud.r-project.org/web/checks/check_results_pkgcache.html","check_result":[{"category":"OK","number_checks":12}],"version":null},{"package":"pkgconfig","url":"https://cloud.r-project.org/web/checks/check_results_pkgconfig.html","check_result":[{"category":"OK","number_checks":12}],"version":null},{"package":"pkgsearch","url":"https://cloud.r-project.org/web/checks/check_results_pkgsearch.html","check_result":[{"category":"OK","number_checks":12}],"version":null},{"package":"praise","url":"https://cloud.r-project.org/web/checks/check_results_praise.html","check_result":[{"category":"OK","number_checks":12}],"version":null},{"package":"presser","url":"https://cloud.r-project.org/web/checks/check_results_presser.html","check_result":[{"category":"ERROR","number_checks":1},{"category":"OK","number_checks":11}],"version":null},{"package":"prettycode","url":"https://cloud.r-project.org/web/checks/check_results_prettycode.html","check_result":[{"category":"OK","number_checks":12}],"version":null},{"package":"prettyunits","url":"https://cloud.r-project.org/web/checks/check_results_prettyunits.html","check_result":[{"category":"OK","number_checks":12}],"version":null},{"package":"processx","url":"https://cloud.r-project.org/web/checks/check_results_processx.html","check_result":[{"category":"WARN","number_checks":1},{"category":"OK","number_checks":11}],"version":null},{"package":"progress","url":"https://cloud.r-project.org/web/checks/check_results_progress.html","check_result":[{"category":"OK","number_checks":12}],"version":null},{"package":"ps","url":"https://cloud.r-project.org/web/checks/check_results_ps.html","check_result":[{"category":"ERROR","number_checks":1},{"category":"OK","number_checks":11}],"version":null},{"package":"rcmdcheck","url":"https://cloud.r-project.org/web/checks/check_results_rcmdcheck.html","check_result":[{"category":"OK","number_checks":12}],"version":null},{"package":"rcorpora","url":"https://cloud.r-project.org/web/checks/check_results_rcorpora.html","check_result":[{"category":"NOTE","number_checks":7},{"category":"OK","number_checks":5}],"version":null},{"package":"rematch2","url":"https://cloud.r-project.org/web/checks/check_results_rematch2.html","check_result":[{"category":"OK","number_checks":12}],"version":null},{"package":"rhub","url":"https://cloud.r-project.org/web/checks/check_results_rhub.html","check_result":[{"category":"OK","number_checks":12}],"version":null},{"package":"rversions","url":"https://cloud.r-project.org/web/checks/check_results_rversions.html","check_result":[{"category":"OK","number_checks":12}],"version":null},{"package":"sand","url":"https://cloud.r-project.org/web/checks/check_results_sand.html","check_result":[{"category":"NOTE","number_checks":11},{"category":"OK","number_checks":1}],"version":null},{"package":"sankey","url":"https://cloud.r-project.org/web/checks/check_results_sankey.html","check_result":[{"category":"OK","number_checks":12}],"version":null},{"package":"secret","url":"https://cloud.r-project.org/web/checks/check_results_secret.html","check_result":[{"category":"OK","number_checks":12}],"version":null},{"package":"sessioninfo","url":"https://cloud.r-project.org/web/checks/check_results_sessioninfo.html","check_result":[{"category":"OK","number_checks":12}],"version":null},{"package":"showimage","url":"https://cloud.r-project.org/web/checks/check_results_showimage.html","check_result":[{"category":"OK","number_checks":12}],"version":null},{"package":"tracer","url":"https://cloud.r-project.org/web/checks/check_results_tracer.html","check_result":[{"category":"OK","number_checks":12}],"version":null},{"package":"webdriver","url":"https://cloud.r-project.org/web/checks/check_results_webdriver.html","check_result":[{"category":"OK","number_checks":12}],"version":null},{"package":"whoami","url":"https://cloud.r-project.org/web/checks/check_results_whoami.html","check_result":[{"category":"OK","number_checks":12}],"version":null},{"package":"xmlparsedata","url":"https://cloud.r-project.org/web/checks/check_results_xmlparsedata.html","check_result":[{"category":"OK","number_checks":12}],"version":null},{"package":"xopen","url":"https://cloud.r-project.org/web/checks/check_results_xopen.html","check_result":[{"category":"OK","number_checks":12}],"version":null},{"package":"zip","url":"https://cloud.r-project.org/web/checks/check_results_zip.html","check_result":[{"category":"OK","number_checks":12}],"version":null}],"date_updated":"2020-05-11T20:00:50.802Z"}}' 32 | recorded_at: 2020-05-11 23:36:40 GMT 33 | recorded_with: vcr/0.5.4, webmockr/0.6.2.92 34 | -------------------------------------------------------------------------------- /tests/fixtures/cch_pkgs_error.yml: -------------------------------------------------------------------------------- 1 | http_interactions: 2 | - request: 3 | method: get 4 | uri: https://cranchecks.info/pkgs?limit=foo&offset=0 5 | body: 6 | encoding: '' 7 | string: '' 8 | headers: 9 | User-Agent: r-curl/4.3 crul/0.9.0 rOpenSci(cchecks/0.1.4.91) 10 | Accept-Encoding: gzip, deflate 11 | Accept: application/json, text/xml, application/xml, */* 12 | Authorization: 'Bearer ' 13 | response: 14 | status: 15 | status_code: '400' 16 | message: Bad Request 17 | explanation: Bad request syntax or unsupported method 18 | headers: 19 | status: 'HTTP/2 400 ' 20 | access-control-allow-methods: HEAD, GET 21 | access-control-allow-origin: '*' 22 | cache-control: public, must-revalidate, max-age=60 23 | content-encoding: gzip 24 | content-type: application/json; charset=utf8 25 | server: Caddy 26 | vary: Accept-Encoding 27 | x-content-type-options: nosniff 28 | content-length: '86' 29 | date: Tue, 05 May 2020 21:45:01 GMT 30 | body: 31 | encoding: UTF-8 32 | file: no 33 | string: '{"count":0,"error":{"message":"limit is not an integer"},"data":null}' 34 | recorded_at: 2020-05-05 21:45:01 GMT 35 | recorded_with: vcr/0.5.4, webmockr/0.6.2 36 | - request: 37 | method: get 38 | uri: https://cranchecks.info/pkgs?limit=10&offset=bar 39 | body: 40 | encoding: '' 41 | string: '' 42 | headers: 43 | User-Agent: r-curl/4.3 crul/0.9.0 rOpenSci(cchecks/0.1.4.91) 44 | Accept-Encoding: gzip, deflate 45 | Accept: application/json, text/xml, application/xml, */* 46 | Authorization: 'Bearer ' 47 | response: 48 | status: 49 | status_code: '400' 50 | message: Bad Request 51 | explanation: Bad request syntax or unsupported method 52 | headers: 53 | status: 'HTTP/2 400 ' 54 | access-control-allow-methods: HEAD, GET 55 | access-control-allow-origin: '*' 56 | cache-control: public, must-revalidate, max-age=60 57 | content-encoding: gzip 58 | content-type: application/json; charset=utf8 59 | server: Caddy 60 | vary: Accept-Encoding 61 | x-content-type-options: nosniff 62 | content-length: '88' 63 | date: Tue, 05 May 2020 21:45:01 GMT 64 | body: 65 | encoding: UTF-8 66 | file: no 67 | string: '{"count":0,"error":{"message":"offset is not an integer"},"data":null}' 68 | recorded_at: 2020-05-05 21:45:01 GMT 69 | recorded_with: vcr/0.5.4, webmockr/0.6.2 70 | - request: 71 | method: get 72 | uri: https://cranchecks.info/pkgs/aaaaaaaaaaa?limit=10&offset=0 73 | body: 74 | encoding: '' 75 | string: '' 76 | headers: 77 | User-Agent: r-curl/4.3 crul/0.9.0 rOpenSci(cchecks/0.1.4.91) 78 | Accept-Encoding: gzip, deflate 79 | Accept: application/json, text/xml, application/xml, */* 80 | Authorization: 'Bearer ' 81 | response: 82 | status: 83 | status_code: '400' 84 | message: Bad Request 85 | explanation: Bad request syntax or unsupported method 86 | headers: 87 | status: 'HTTP/2 400 ' 88 | access-control-allow-methods: HEAD, GET 89 | access-control-allow-origin: '*' 90 | cache-control: public, must-revalidate, max-age=60 91 | content-encoding: gzip 92 | content-type: application/json; charset=utf8 93 | server: Caddy 94 | vary: Accept-Encoding 95 | x-content-type-options: nosniff 96 | content-length: '76' 97 | date: Tue, 05 May 2020 21:45:01 GMT 98 | body: 99 | encoding: UTF-8 100 | file: no 101 | string: '{"error":{"message":"no results found"},"data":null}' 102 | recorded_at: 2020-05-05 21:45:01 GMT 103 | recorded_with: vcr/0.5.4, webmockr/0.6.2 104 | -------------------------------------------------------------------------------- /tests/fixtures/cch_pkgs_history_error.yml: -------------------------------------------------------------------------------- 1 | http_interactions: 2 | - request: 3 | method: get 4 | uri: https://cranchecks.info/pkgs/x/history?limit=foo&offset=0 5 | body: 6 | encoding: '' 7 | string: '' 8 | headers: 9 | User-Agent: r-curl/4.3 crul/0.9.0 rOpenSci(cchecks/0.1.5.97) 10 | Accept-Encoding: gzip, deflate 11 | Accept: application/json, text/xml, application/xml, */* 12 | response: 13 | status: 14 | status_code: '400' 15 | message: Bad Request 16 | explanation: Bad request syntax or unsupported method 17 | headers: 18 | status: 'HTTP/2 400 ' 19 | access-control-allow-methods: HEAD, GET 20 | access-control-allow-origin: '*' 21 | cache-control: public, must-revalidate, max-age=60 22 | content-encoding: gzip 23 | content-type: application/json; charset=utf8 24 | server: Caddy 25 | vary: Accept-Encoding 26 | x-content-type-options: nosniff 27 | content-length: '80' 28 | date: Wed, 20 May 2020 00:19:07 GMT 29 | body: 30 | encoding: UTF-8 31 | file: no 32 | string: '{"error":{"message":"limit is not an integer"},"data":null}' 33 | recorded_at: 2020-05-20 00:19:07 GMT 34 | recorded_with: vcr/0.5.4, webmockr/0.6.2 35 | - request: 36 | method: get 37 | uri: https://cranchecks.info/pkgs/x/history?limit=30&offset=bar 38 | body: 39 | encoding: '' 40 | string: '' 41 | headers: 42 | User-Agent: r-curl/4.3 crul/0.9.0 rOpenSci(cchecks/0.1.5.97) 43 | Accept-Encoding: gzip, deflate 44 | Accept: application/json, text/xml, application/xml, */* 45 | response: 46 | status: 47 | status_code: '400' 48 | message: Bad Request 49 | explanation: Bad request syntax or unsupported method 50 | headers: 51 | status: 'HTTP/2 400 ' 52 | access-control-allow-methods: HEAD, GET 53 | access-control-allow-origin: '*' 54 | cache-control: public, must-revalidate, max-age=60 55 | content-encoding: gzip 56 | content-type: application/json; charset=utf8 57 | server: Caddy 58 | vary: Accept-Encoding 59 | x-content-type-options: nosniff 60 | content-length: '81' 61 | date: Wed, 20 May 2020 00:19:07 GMT 62 | body: 63 | encoding: UTF-8 64 | file: no 65 | string: '{"error":{"message":"offset is not an integer"},"data":null}' 66 | recorded_at: 2020-05-20 00:19:07 GMT 67 | recorded_with: vcr/0.5.4, webmockr/0.6.2 68 | - request: 69 | method: get 70 | uri: https://cranchecks.info/pkgs/aaaaaaaaaaa/history?limit=30&offset=0 71 | body: 72 | encoding: '' 73 | string: '' 74 | headers: 75 | User-Agent: r-curl/4.3 crul/0.9.0 rOpenSci(cchecks/0.1.5.97) 76 | Accept-Encoding: gzip, deflate 77 | Accept: application/json, text/xml, application/xml, */* 78 | response: 79 | status: 80 | status_code: '400' 81 | message: Bad Request 82 | explanation: Bad request syntax or unsupported method 83 | headers: 84 | status: 'HTTP/2 400 ' 85 | access-control-allow-methods: HEAD, GET 86 | access-control-allow-origin: '*' 87 | cache-control: public, must-revalidate, max-age=60 88 | content-encoding: gzip 89 | content-type: application/json; charset=utf8 90 | server: Caddy 91 | vary: Accept-Encoding 92 | x-content-type-options: nosniff 93 | content-length: '76' 94 | date: Wed, 20 May 2020 00:19:07 GMT 95 | body: 96 | encoding: UTF-8 97 | file: no 98 | string: '{"error":{"message":"no results found"},"data":null}' 99 | recorded_at: 2020-05-20 00:19:07 GMT 100 | recorded_with: vcr/0.5.4, webmockr/0.6.2 101 | -------------------------------------------------------------------------------- /tests/fixtures/cch_pkgs_one_pkg.yml: -------------------------------------------------------------------------------- 1 | http_interactions: 2 | - request: 3 | method: get 4 | uri: https://cranchecks.info/pkgs/worrms?limit=10&offset=0 5 | body: 6 | encoding: '' 7 | string: '' 8 | headers: 9 | User-Agent: r-curl/4.3 crul/0.9.0 rOpenSci(cchecks/0.1.4.91) 10 | Accept-Encoding: gzip, deflate 11 | Accept: application/json, text/xml, application/xml, */* 12 | Authorization: 'Bearer ' 13 | response: 14 | status: 15 | status_code: '200' 16 | message: OK 17 | explanation: Request fulfilled, document follows 18 | headers: 19 | status: 'HTTP/2 200 ' 20 | access-control-allow-methods: HEAD, GET 21 | access-control-allow-origin: '*' 22 | cache-control: public, must-revalidate, max-age=60 23 | content-encoding: gzip 24 | content-type: application/json; charset=utf8 25 | server: Caddy 26 | vary: Accept-Encoding 27 | x-content-type-options: nosniff 28 | content-length: '559' 29 | date: Tue, 05 May 2020 21:52:59 GMT 30 | body: 31 | encoding: UTF-8 32 | file: no 33 | string: '{"error":null,"data":{"_id":"worrms","package":"worrms","url":"https://cloud.r-project.org/web/checks/check_results_worrms.html","summary":{"any":false,"ok":12,"note":0,"warn":0,"error":0,"fail":0},"checks":[{"flavor":"r-devel-linux-x86_64-debian-clang","version":"0.4.0","tinstall":2.86,"tcheck":36.05,"ttotal":38.91,"status":"OK","check_url":"https://www.R-project.org/nosvn/R.check/r-devel-linux-x86_64-debian-clang/worrms-00check.html"},{"flavor":"r-devel-linux-x86_64-debian-gcc","version":"0.4.0","tinstall":2.05,"tcheck":28.85,"ttotal":30.9,"status":"OK","check_url":"https://www.R-project.org/nosvn/R.check/r-devel-linux-x86_64-debian-gcc/worrms-00check.html"},{"flavor":"r-devel-linux-x86_64-fedora-clang","version":"0.4.0","tinstall":0.0,"tcheck":0.0,"ttotal":48.89,"status":"OK","check_url":"https://www.R-project.org/nosvn/R.check/r-devel-linux-x86_64-fedora-clang/worrms-00check.html"},{"flavor":"r-devel-linux-x86_64-fedora-gcc","version":"0.4.0","tinstall":0.0,"tcheck":0.0,"ttotal":47.62,"status":"OK","check_url":"https://www.R-project.org/nosvn/R.check/r-devel-linux-x86_64-fedora-gcc/worrms-00check.html"},{"flavor":"r-devel-windows-ix86+x86_64","version":"0.4.0","tinstall":10.0,"tcheck":75.0,"ttotal":85.0,"status":"OK","check_url":"https://www.R-project.org/nosvn/R.check/r-devel-windows-ix86+x86_64/worrms-00check.html"},{"flavor":"r-patched-linux-x86_64","version":"0.4.0","tinstall":2.63,"tcheck":35.85,"ttotal":38.48,"status":"OK","check_url":"https://www.R-project.org/nosvn/R.check/r-patched-linux-x86_64/worrms-00check.html"},{"flavor":"r-patched-solaris-x86","version":"0.4.0","tinstall":0.0,"tcheck":0.0,"ttotal":66.9,"status":"OK","check_url":"https://www.R-project.org/nosvn/R.check/r-patched-solaris-x86/worrms-00check.html"},{"flavor":"r-release-linux-x86_64","version":"0.4.0","tinstall":2.64,"tcheck":35.35,"ttotal":37.99,"status":"OK","check_url":"https://www.R-project.org/nosvn/R.check/r-release-linux-x86_64/worrms-00check.html"},{"flavor":"r-release-osx-x86_64","version":"0.4.0","tinstall":0.0,"tcheck":0.0,"ttotal":0.0,"status":"OK","check_url":"https://www.R-project.org/nosvn/R.check/r-release-osx-x86_64/worrms-00check.html"},{"flavor":"r-release-windows-ix86+x86_64","version":"0.4.0","tinstall":9.0,"tcheck":74.0,"ttotal":83.0,"status":"OK","check_url":"https://www.R-project.org/nosvn/R.check/r-release-windows-ix86+x86_64/worrms-00check.html"},{"flavor":"r-oldrel-osx-x86_64","version":"0.4.0","tinstall":0.0,"tcheck":0.0,"ttotal":0.0,"status":"OK","check_url":"https://www.R-project.org/nosvn/R.check/r-oldrel-osx-x86_64/worrms-00check.html"},{"flavor":"r-oldrel-windows-ix86+x86_64","version":"0.4.0","tinstall":6.0,"tcheck":68.0,"ttotal":74.0,"status":"OK","check_url":"https://www.R-project.org/nosvn/R.check/r-oldrel-windows-ix86+x86_64/worrms-00check.html"}],"check_details":null,"date_updated":"2020-05-05T21:03:16.145Z"}}' 34 | recorded_at: 2020-05-05 21:52:59 GMT 35 | recorded_with: vcr/0.5.4, webmockr/0.6.2 36 | -------------------------------------------------------------------------------- /tests/fixtures/cch_pkgs_search_error.yml: -------------------------------------------------------------------------------- 1 | http_interactions: 2 | - request: 3 | method: get 4 | uri: https://cranchecks.info/search?q=foo&one_each=false&limit=foo&offset=0 5 | body: 6 | encoding: '' 7 | string: '' 8 | headers: 9 | User-Agent: r-curl/4.3 crul/0.9.0 rOpenSci(cchecks/0.1.7.91) 10 | Accept-Encoding: gzip, deflate 11 | Accept: application/json, text/xml, application/xml, */* 12 | response: 13 | status: 14 | status_code: '400' 15 | message: Bad Request 16 | explanation: Bad request syntax or unsupported method 17 | headers: 18 | status: 'HTTP/2 400 ' 19 | access-control-allow-methods: HEAD, GET 20 | access-control-allow-origin: '*' 21 | cache-control: public, must-revalidate, max-age=60 22 | content-encoding: gzip 23 | content-type: application/json 24 | server: Caddy 25 | vary: Accept-Encoding 26 | x-content-type-options: nosniff 27 | content-length: '71' 28 | date: Wed, 20 May 2020 14:56:26 GMT 29 | body: 30 | encoding: UTF-8 31 | file: no 32 | string: '{"error":{"message":"limit is not an integer"}}' 33 | recorded_at: 2020-05-20 14:56:26 GMT 34 | recorded_with: vcr/0.5.4, webmockr/0.6.2 35 | - request: 36 | method: get 37 | uri: https://cranchecks.info/search?q=foo&one_each=false&limit=30&offset=bar 38 | body: 39 | encoding: '' 40 | string: '' 41 | headers: 42 | User-Agent: r-curl/4.3 crul/0.9.0 rOpenSci(cchecks/0.1.7.91) 43 | Accept-Encoding: gzip, deflate 44 | Accept: application/json, text/xml, application/xml, */* 45 | response: 46 | status: 47 | status_code: '400' 48 | message: Bad Request 49 | explanation: Bad request syntax or unsupported method 50 | headers: 51 | status: 'HTTP/2 400 ' 52 | access-control-allow-methods: HEAD, GET 53 | access-control-allow-origin: '*' 54 | cache-control: public, must-revalidate, max-age=60 55 | content-encoding: gzip 56 | content-type: application/json 57 | server: Caddy 58 | vary: Accept-Encoding 59 | x-content-type-options: nosniff 60 | content-length: '71' 61 | date: Wed, 20 May 2020 14:56:26 GMT 62 | body: 63 | encoding: UTF-8 64 | file: no 65 | string: '{"error":{"message":"offset is not an integer"}}' 66 | recorded_at: 2020-05-20 14:56:26 GMT 67 | recorded_with: vcr/0.5.4, webmockr/0.6.2 68 | - request: 69 | method: get 70 | uri: https://cranchecks.info/search?q=aaaaaaaaaaa&one_each=false&limit=30&offset=0 71 | body: 72 | encoding: '' 73 | string: '' 74 | headers: 75 | User-Agent: r-curl/4.3 crul/0.9.0 rOpenSci(cchecks/0.1.7.91) 76 | Accept-Encoding: gzip, deflate 77 | Accept: application/json, text/xml, application/xml, */* 78 | response: 79 | status: 80 | status_code: '400' 81 | message: Bad Request 82 | explanation: Bad request syntax or unsupported method 83 | headers: 84 | status: 'HTTP/2 400 ' 85 | access-control-allow-methods: HEAD, GET 86 | access-control-allow-origin: '*' 87 | cache-control: public, must-revalidate, max-age=60 88 | content-encoding: gzip 89 | content-type: application/json 90 | server: Caddy 91 | vary: Accept-Encoding 92 | x-content-type-options: nosniff 93 | content-length: '64' 94 | date: Wed, 20 May 2020 14:56:26 GMT 95 | body: 96 | encoding: UTF-8 97 | file: no 98 | string: '{"error":{"message":"no results found"}}' 99 | recorded_at: 2020-05-20 14:56:26 GMT 100 | recorded_with: vcr/0.5.4, webmockr/0.6.2 101 | -------------------------------------------------------------------------------- /tests/fixtures/cch_pkgs_search_limit_by_package.yml: -------------------------------------------------------------------------------- 1 | http_interactions: 2 | - request: 3 | method: get 4 | uri: https://cranchecks.info/search?q=memory&package=apsimr&one_each=false&limit=30&offset=0 5 | body: 6 | encoding: '' 7 | string: '' 8 | headers: 9 | User-Agent: r-curl/4.3 crul/0.9.0 rOpenSci(cchecks/0.1.7.91) 10 | Accept-Encoding: gzip, deflate 11 | Accept: application/json, text/xml, application/xml, */* 12 | response: 13 | status: 14 | status_code: '200' 15 | message: OK 16 | explanation: Request fulfilled, document follows 17 | headers: 18 | status: 'HTTP/2 200 ' 19 | access-control-allow-methods: HEAD, GET 20 | access-control-allow-origin: '*' 21 | cache-control: public, must-revalidate, max-age=60 22 | content-encoding: gzip 23 | content-type: application/json; charset=utf8 24 | server: Caddy 25 | vary: Accept-Encoding 26 | x-content-type-options: nosniff 27 | content-length: '1246' 28 | date: Wed, 20 May 2020 14:56:26 GMT 29 | body: 30 | encoding: UTF-8 31 | file: no 32 | string: '{"error":null,"count":3,"returned":3,"data":[{"package":"apsimr","date_updated":"2020-04-20T15:03:30.000Z","summary":{"any":true,"ok":12,"note":0,"warn":1,"error":0,"fail":0},"checks":[{"flavor":"r-devel-linux-x86_64-debian-clang","version":"1.2","tinstall":10.7,"tcheck":99.81,"ttotal":110.51,"status":"OK","check_url":"https://www.R-project.org/nosvn/R.check/r-devel-linux-x86_64-debian-clang/apsimr-00check.html"},{"flavor":"r-devel-linux-x86_64-debian-gcc","version":"1.2","tinstall":9.03,"tcheck":76.48,"ttotal":85.51,"status":"OK","check_url":"https://www.R-project.org/nosvn/R.check/r-devel-linux-x86_64-debian-gcc/apsimr-00check.html"},{"flavor":"r-devel-linux-x86_64-fedora-clang","version":"1.2","tinstall":0.0,"tcheck":0.0,"ttotal":134.22,"status":"OK","check_url":"https://www.R-project.org/nosvn/R.check/r-devel-linux-x86_64-fedora-clang/apsimr-00check.html"},{"flavor":"r-devel-linux-x86_64-fedora-gcc","version":"1.2","tinstall":0.0,"tcheck":0.0,"ttotal":134.99,"status":"OK","check_url":"https://www.R-project.org/nosvn/R.check/r-devel-linux-x86_64-fedora-gcc/apsimr-00check.html"},{"flavor":"r-devel-windows-ix86+x86_64","version":"1.2","tinstall":42.0,"tcheck":110.0,"ttotal":152.0,"status":"OK","check_url":"https://www.R-project.org/nosvn/R.check/r-devel-windows-ix86+x86_64/apsimr-00check.html"},{"flavor":"r-patched-linux-x86_64","version":"1.2","tinstall":10.05,"tcheck":95.08,"ttotal":105.13,"status":"OK","check_url":"https://www.R-project.org/nosvn/R.check/r-patched-linux-x86_64/apsimr-00check.html"},{"flavor":"r-patched-osx-x86_64","version":"1.2","tinstall":0.0,"tcheck":0.0,"ttotal":0.0,"status":"OK","check_url":"https://www.R-project.org/nosvn/R.check/r-patched-osx-x86_64/apsimr-00check.html"},{"flavor":"r-patched-solaris-x86","version":"1.2","tinstall":0.0,"tcheck":0.0,"ttotal":208.6,"status":"OK","check_url":"https://www.R-project.org/nosvn/R.check/r-patched-solaris-x86/apsimr-00check.html"},{"flavor":"r-release-linux-x86_64","version":"1.2","tinstall":8.87,"tcheck":87.46,"ttotal":96.33,"status":"OK","check_url":"https://www.R-project.org/nosvn/R.check/r-release-linux-x86_64/apsimr-00check.html"},{"flavor":"r-release-windows-ix86+x86_64","version":"1.2","tinstall":21.0,"tcheck":126.0,"ttotal":147.0,"status":"OK","check_url":"https://www.R-project.org/nosvn/R.check/r-release-windows-ix86+x86_64/apsimr-00check.html"},{"flavor":"r-release-osx-x86_64","version":"1.2","tinstall":0.0,"tcheck":0.0,"ttotal":0.0,"status":"OK","check_url":"https://www.R-project.org/nosvn/R.check/r-release-osx-x86_64/apsimr-00check.html"},{"flavor":"r-oldrel-windows-ix86+x86_64","version":"1.2","tinstall":20.0,"tcheck":151.0,"ttotal":171.0,"status":"WARN","check_url":"https://www.R-project.org/nosvn/R.check/r-oldrel-windows-ix86+x86_64/apsimr-00check.html"},{"flavor":"r-oldrel-osx-x86_64","version":"1.2","tinstall":0.0,"tcheck":0.0,"ttotal":0.0,"status":"OK","check_url":"https://www.R-project.org/nosvn/R.check/r-oldrel-osx-x86_64/apsimr-00check.html"}],"check_details":{"version":"1.2","check":"Rd 33 | \\usage sections","result":"WARN","output":"Error in sub(re, \"\\\\\\\\S4method{\\\\2\\\\7}{\\\\3}\", 34 | x) : \n invalid regular expression ''(\\\\S4method\\{([._[:alnum:]]*|\\$|\\[\\[?|\\+|\\-|\\*|\\/|\\^|\u003c=?|\u003e=?|!=?|==|\\\u0026|\\||\\%[[:alnum:][:punct:]]*\\%)\\}\\{((([._[:alnum:]]+|`[^`]+`),)*([._[:alnum:]]+|`[^`]+`))\\})(\u003c-)?'', 35 | reason ''Out of memory''\nCalls: \u003cAnonymous\u003e ... .transform_S4_method_markup 36 | -\u003e .strip_backticks -\u003e gsub -\u003e sub\nExecution halted\nFunctions 37 | with \\usage entries need to have the appropriate \\alias\nentries, and all 38 | their arguments documented.\nThe \\usage entries must correspond to syntactically 39 | valid R code.\nSee chapter ''Writing R documentation files'' in the ''Writing 40 | R\nExtensions'' manual.","flavors":["r-oldrel-windows-ix86+x86_64"],"additional_issues":[]}},{"package":"apsimr","date_updated":"2020-04-21T15:03:23.000Z","summary":{"any":true,"ok":12,"note":0,"warn":1,"error":0,"fail":0},"checks":[{"flavor":"r-devel-linux-x86_64-debian-clang","version":"1.2","tinstall":10.7,"tcheck":99.81,"ttotal":110.51,"status":"OK","check_url":"https://www.R-project.org/nosvn/R.check/r-devel-linux-x86_64-debian-clang/apsimr-00check.html"},{"flavor":"r-devel-linux-x86_64-debian-gcc","version":"1.2","tinstall":9.72,"tcheck":76.09,"ttotal":85.81,"status":"OK","check_url":"https://www.R-project.org/nosvn/R.check/r-devel-linux-x86_64-debian-gcc/apsimr-00check.html"},{"flavor":"r-devel-linux-x86_64-fedora-clang","version":"1.2","tinstall":0.0,"tcheck":0.0,"ttotal":134.22,"status":"OK","check_url":"https://www.R-project.org/nosvn/R.check/r-devel-linux-x86_64-fedora-clang/apsimr-00check.html"},{"flavor":"r-devel-linux-x86_64-fedora-gcc","version":"1.2","tinstall":0.0,"tcheck":0.0,"ttotal":134.99,"status":"OK","check_url":"https://www.R-project.org/nosvn/R.check/r-devel-linux-x86_64-fedora-gcc/apsimr-00check.html"},{"flavor":"r-devel-windows-ix86+x86_64","version":"1.2","tinstall":42.0,"tcheck":110.0,"ttotal":152.0,"status":"OK","check_url":"https://www.R-project.org/nosvn/R.check/r-devel-windows-ix86+x86_64/apsimr-00check.html"},{"flavor":"r-patched-linux-x86_64","version":"1.2","tinstall":10.88,"tcheck":95.23,"ttotal":106.11,"status":"OK","check_url":"https://www.R-project.org/nosvn/R.check/r-patched-linux-x86_64/apsimr-00check.html"},{"flavor":"r-patched-osx-x86_64","version":"1.2","tinstall":0.0,"tcheck":0.0,"ttotal":0.0,"status":"OK","check_url":"https://www.R-project.org/nosvn/R.check/r-patched-osx-x86_64/apsimr-00check.html"},{"flavor":"r-patched-solaris-x86","version":"1.2","tinstall":0.0,"tcheck":0.0,"ttotal":208.6,"status":"OK","check_url":"https://www.R-project.org/nosvn/R.check/r-patched-solaris-x86/apsimr-00check.html"},{"flavor":"r-release-linux-x86_64","version":"1.2","tinstall":8.05,"tcheck":86.93,"ttotal":94.98,"status":"OK","check_url":"https://www.R-project.org/nosvn/R.check/r-release-linux-x86_64/apsimr-00check.html"},{"flavor":"r-release-windows-ix86+x86_64","version":"1.2","tinstall":18.0,"tcheck":101.0,"ttotal":119.0,"status":"OK","check_url":"https://www.R-project.org/nosvn/R.check/r-release-windows-ix86+x86_64/apsimr-00check.html"},{"flavor":"r-release-osx-x86_64","version":"1.2","tinstall":0.0,"tcheck":0.0,"ttotal":0.0,"status":"OK","check_url":"https://www.R-project.org/nosvn/R.check/r-release-osx-x86_64/apsimr-00check.html"},{"flavor":"r-oldrel-windows-ix86+x86_64","version":"1.2","tinstall":20.0,"tcheck":151.0,"ttotal":171.0,"status":"WARN","check_url":"https://www.R-project.org/nosvn/R.check/r-oldrel-windows-ix86+x86_64/apsimr-00check.html"},{"flavor":"r-oldrel-osx-x86_64","version":"1.2","tinstall":0.0,"tcheck":0.0,"ttotal":0.0,"status":"OK","check_url":"https://www.R-project.org/nosvn/R.check/r-oldrel-osx-x86_64/apsimr-00check.html"}],"check_details":{"version":"1.2","check":"Rd 41 | \\usage sections","result":"WARN","output":"Error in sub(re, \"\\\\\\\\S4method{\\\\2\\\\7}{\\\\3}\", 42 | x) : \n invalid regular expression ''(\\\\S4method\\{([._[:alnum:]]*|\\$|\\[\\[?|\\+|\\-|\\*|\\/|\\^|\u003c=?|\u003e=?|!=?|==|\\\u0026|\\||\\%[[:alnum:][:punct:]]*\\%)\\}\\{((([._[:alnum:]]+|`[^`]+`),)*([._[:alnum:]]+|`[^`]+`))\\})(\u003c-)?'', 43 | reason ''Out of memory''\nCalls: \u003cAnonymous\u003e ... .transform_S4_method_markup 44 | -\u003e .strip_backticks -\u003e gsub -\u003e sub\nExecution halted\nFunctions 45 | with \\usage entries need to have the appropriate \\alias\nentries, and all 46 | their arguments documented.\nThe \\usage entries must correspond to syntactically 47 | valid R code.\nSee chapter ''Writing R documentation files'' in the ''Writing 48 | R\nExtensions'' manual.","flavors":["r-oldrel-windows-ix86+x86_64"],"additional_issues":[]}},{"package":"apsimr","date_updated":"2020-04-22T15:03:24.000Z","summary":{"any":true,"ok":12,"note":0,"warn":1,"error":0,"fail":0},"checks":[{"flavor":"r-devel-linux-x86_64-debian-clang","version":"1.2","tinstall":10.5,"tcheck":99.09,"ttotal":109.59,"status":"OK","check_url":"https://www.R-project.org/nosvn/R.check/r-devel-linux-x86_64-debian-clang/apsimr-00check.html"},{"flavor":"r-devel-linux-x86_64-debian-gcc","version":"1.2","tinstall":8.18,"tcheck":76.66,"ttotal":84.84,"status":"OK","check_url":"https://www.R-project.org/nosvn/R.check/r-devel-linux-x86_64-debian-gcc/apsimr-00check.html"},{"flavor":"r-devel-linux-x86_64-fedora-clang","version":"1.2","tinstall":0.0,"tcheck":0.0,"ttotal":134.22,"status":"OK","check_url":"https://www.R-project.org/nosvn/R.check/r-devel-linux-x86_64-fedora-clang/apsimr-00check.html"},{"flavor":"r-devel-linux-x86_64-fedora-gcc","version":"1.2","tinstall":0.0,"tcheck":0.0,"ttotal":134.99,"status":"OK","check_url":"https://www.R-project.org/nosvn/R.check/r-devel-linux-x86_64-fedora-gcc/apsimr-00check.html"},{"flavor":"r-devel-windows-ix86+x86_64","version":"1.2","tinstall":42.0,"tcheck":110.0,"ttotal":152.0,"status":"OK","check_url":"https://www.R-project.org/nosvn/R.check/r-devel-windows-ix86+x86_64/apsimr-00check.html"},{"flavor":"r-patched-linux-x86_64","version":"1.2","tinstall":10.88,"tcheck":95.23,"ttotal":106.11,"status":"OK","check_url":"https://www.R-project.org/nosvn/R.check/r-patched-linux-x86_64/apsimr-00check.html"},{"flavor":"r-patched-osx-x86_64","version":"1.2","tinstall":0.0,"tcheck":0.0,"ttotal":0.0,"status":"OK","check_url":"https://www.R-project.org/nosvn/R.check/r-patched-osx-x86_64/apsimr-00check.html"},{"flavor":"r-patched-solaris-x86","version":"1.2","tinstall":0.0,"tcheck":0.0,"ttotal":208.6,"status":"OK","check_url":"https://www.R-project.org/nosvn/R.check/r-patched-solaris-x86/apsimr-00check.html"},{"flavor":"r-release-linux-x86_64","version":"1.2","tinstall":8.05,"tcheck":86.93,"ttotal":94.98,"status":"OK","check_url":"https://www.R-project.org/nosvn/R.check/r-release-linux-x86_64/apsimr-00check.html"},{"flavor":"r-release-windows-ix86+x86_64","version":"1.2","tinstall":18.0,"tcheck":101.0,"ttotal":119.0,"status":"OK","check_url":"https://www.R-project.org/nosvn/R.check/r-release-windows-ix86+x86_64/apsimr-00check.html"},{"flavor":"r-release-osx-x86_64","version":"1.2","tinstall":0.0,"tcheck":0.0,"ttotal":0.0,"status":"OK","check_url":"https://www.R-project.org/nosvn/R.check/r-release-osx-x86_64/apsimr-00check.html"},{"flavor":"r-oldrel-windows-ix86+x86_64","version":"1.2","tinstall":20.0,"tcheck":151.0,"ttotal":171.0,"status":"WARN","check_url":"https://www.R-project.org/nosvn/R.check/r-oldrel-windows-ix86+x86_64/apsimr-00check.html"},{"flavor":"r-oldrel-osx-x86_64","version":"1.2","tinstall":0.0,"tcheck":0.0,"ttotal":0.0,"status":"OK","check_url":"https://www.R-project.org/nosvn/R.check/r-oldrel-osx-x86_64/apsimr-00check.html"}],"check_details":{"version":"1.2","check":"Rd 49 | \\usage sections","result":"WARN","output":"Error in sub(re, \"\\\\\\\\S4method{\\\\2\\\\7}{\\\\3}\", 50 | x) : \n invalid regular expression ''(\\\\S4method\\{([._[:alnum:]]*|\\$|\\[\\[?|\\+|\\-|\\*|\\/|\\^|\u003c=?|\u003e=?|!=?|==|\\\u0026|\\||\\%[[:alnum:][:punct:]]*\\%)\\}\\{((([._[:alnum:]]+|`[^`]+`),)*([._[:alnum:]]+|`[^`]+`))\\})(\u003c-)?'', 51 | reason ''Out of memory''\nCalls: \u003cAnonymous\u003e ... .transform_S4_method_markup 52 | -\u003e .strip_backticks -\u003e gsub -\u003e sub\nExecution halted\nFunctions 53 | with \\usage entries need to have the appropriate \\alias\nentries, and all 54 | their arguments documented.\nThe \\usage entries must correspond to syntactically 55 | valid R code.\nSee chapter ''Writing R documentation files'' in the ''Writing 56 | R\nExtensions'' manual.","flavors":["r-oldrel-windows-ix86+x86_64"],"additional_issues":[]}}]}' 57 | recorded_at: 2020-05-20 14:56:26 GMT 58 | recorded_with: vcr/0.5.4, webmockr/0.6.2 59 | -------------------------------------------------------------------------------- /tests/fixtures/cchn_pkg_rule_add.yml: -------------------------------------------------------------------------------- 1 | http_interactions: 2 | - request: 3 | method: post 4 | uri: https://cranchecks.info/notifications/rules 5 | body: 6 | encoding: '' 7 | string: '[{"package":"bubbles","status":"note","platforms":3}]' 8 | headers: 9 | User-Agent: r-curl/4.3 crul/0.9.0 rOpenSci(cchecks/0.1.8.94) 10 | Accept-Encoding: gzip, deflate 11 | Accept: application/json, text/xml, application/xml, */* 12 | Authorization: Bearer <> 13 | Content-Type: application/json 14 | response: 15 | status: 16 | status_code: '200' 17 | message: OK 18 | explanation: Request fulfilled, document follows 19 | headers: 20 | status: 'HTTP/2 200 ' 21 | access-control-allow-methods: POST 22 | access-control-allow-origin: '*' 23 | cache-control: public, must-revalidate, max-age=60 24 | content-type: application/json; charset=utf8 25 | server: Caddy 26 | x-content-type-options: nosniff 27 | content-length: '120' 28 | date: Fri, 22 May 2020 20:56:30 GMT 29 | body: 30 | encoding: UTF-8 31 | file: no 32 | string: '{"error":null,"data":[{"id":279,"already_existed":true,"rule":"package:bubbles, 33 | status:note, flavor:3, time:, regex:"}]}' 34 | recorded_at: 2020-05-22 20:56:30 GMT 35 | recorded_with: vcr/0.5.4, webmockr/0.6.2 36 | - request: 37 | method: get 38 | uri: https://cranchecks.info/notifications/rules?package=bubbles 39 | body: 40 | encoding: '' 41 | string: '' 42 | headers: 43 | User-Agent: r-curl/4.3 crul/0.9.0 rOpenSci(cchecks/0.1.8.94) 44 | Accept-Encoding: gzip, deflate 45 | Accept: application/json, text/xml, application/xml, */* 46 | Authorization: Bearer <> 47 | response: 48 | status: 49 | status_code: '200' 50 | message: OK 51 | explanation: Request fulfilled, document follows 52 | headers: 53 | status: 'HTTP/2 200 ' 54 | content-type: text/html;charset=utf-8 55 | server: Caddy 56 | x-content-type-options: nosniff 57 | x-frame-options: SAMEORIGIN 58 | x-xss-protection: 1; mode=block 59 | content-length: '131' 60 | date: Fri, 22 May 2020 20:56:30 GMT 61 | body: 62 | encoding: UTF-8 63 | file: no 64 | string: '{"error":null,"data":[{"id":279,"package":"bubbles","rule_status":"note","rule_time":null,"rule_platforms":"3","rule_regex":null}]}' 65 | recorded_at: 2020-05-22 20:56:30 GMT 66 | recorded_with: vcr/0.5.4, webmockr/0.6.2 67 | -------------------------------------------------------------------------------- /tests/fixtures/cchn_pkg_rule_add_cleanup.yml: -------------------------------------------------------------------------------- 1 | http_interactions: 2 | - request: 3 | method: delete 4 | uri: https://cranchecks.info/notifications/rules/279 5 | body: 6 | encoding: '' 7 | string: '' 8 | headers: 9 | User-Agent: r-curl/4.3 crul/0.9.0 rOpenSci(cchecks/0.1.8.94) 10 | Accept-Encoding: gzip, deflate 11 | Accept: application/json, text/xml, application/xml, */* 12 | Authorization: Bearer <> 13 | response: 14 | status: 15 | status_code: '204' 16 | message: No Content 17 | explanation: Request fulfilled, nothing follows 18 | headers: 19 | status: 'HTTP/2 204 ' 20 | access-control-allow-methods: DELETE 21 | server: Caddy 22 | x-content-type-options: nosniff 23 | date: Fri, 22 May 2020 20:57:04 GMT 24 | body: 25 | encoding: UTF-8 26 | file: no 27 | string: '' 28 | recorded_at: 2020-05-22 20:57:04 GMT 29 | recorded_with: vcr/0.5.4, webmockr/0.6.2 30 | -------------------------------------------------------------------------------- /tests/fixtures/cchn_pkg_rule_get_add_rule.yml: -------------------------------------------------------------------------------- 1 | http_interactions: 2 | - request: 3 | method: post 4 | uri: https://cranchecks.info/notifications/rules 5 | body: 6 | encoding: '' 7 | string: '[{"package":"honeybadger","status":"warn","time":6}]' 8 | headers: 9 | User-Agent: r-curl/4.3 crul/0.9.0 rOpenSci(cchecks/0.1.5.95) 10 | Accept-Encoding: gzip, deflate 11 | Accept: application/json, text/xml, application/xml, */* 12 | Authorization: Bearer <> 13 | Content-Type: application/json 14 | response: 15 | status: 16 | status_code: '200' 17 | message: OK 18 | explanation: Request fulfilled, document follows 19 | headers: 20 | status: 'HTTP/2 200 ' 21 | access-control-allow-methods: POST 22 | access-control-allow-origin: '*' 23 | cache-control: public, must-revalidate, max-age=60 24 | content-encoding: gzip 25 | content-type: application/json; charset=utf8 26 | server: Caddy 27 | vary: Accept-Encoding 28 | x-content-type-options: nosniff 29 | content-length: '55' 30 | date: Tue, 19 May 2020 21:00:15 GMT 31 | body: 32 | encoding: UTF-8 33 | file: no 34 | string: '{"error":null,"data":"success"}' 35 | recorded_at: 2020-05-19 21:00:15 GMT 36 | recorded_with: vcr/0.5.4, webmockr/0.6.2 37 | -------------------------------------------------------------------------------- /tests/fixtures/cchn_pkg_rule_get_cleanup.yml: -------------------------------------------------------------------------------- 1 | http_interactions: 2 | - request: 3 | method: delete 4 | uri: https://cranchecks.info/notifications/rules/247 5 | body: 6 | encoding: '' 7 | string: '' 8 | headers: 9 | User-Agent: r-curl/4.3 crul/0.9.0 rOpenSci(cchecks/0.1.5.95) 10 | Accept-Encoding: gzip, deflate 11 | Accept: application/json, text/xml, application/xml, */* 12 | Authorization: Bearer <> 13 | response: 14 | status: 15 | status_code: '204' 16 | message: No Content 17 | explanation: Request fulfilled, nothing follows 18 | headers: 19 | status: 'HTTP/2 204 ' 20 | access-control-allow-methods: DELETE 21 | content-encoding: gzip 22 | server: Caddy 23 | vary: Accept-Encoding 24 | x-content-type-options: nosniff 25 | date: Tue, 19 May 2020 21:00:15 GMT 26 | body: 27 | encoding: UTF-8 28 | file: no 29 | string: '' 30 | recorded_at: 2020-05-19 21:00:15 GMT 31 | recorded_with: vcr/0.5.4, webmockr/0.6.2 32 | -------------------------------------------------------------------------------- /tests/fixtures/cchn_pkg_rule_get_not_found.yml: -------------------------------------------------------------------------------- 1 | http_interactions: 2 | - request: 3 | method: get 4 | uri: https://cranchecks.info/notifications/rules/578999 5 | body: 6 | encoding: '' 7 | string: '' 8 | headers: 9 | User-Agent: r-curl/4.3 crul/0.9.0 rOpenSci(cchecks/0.1.5.95) 10 | Accept-Encoding: gzip, deflate 11 | Accept: application/json, text/xml, application/xml, */* 12 | Authorization: Bearer <> 13 | response: 14 | status: 15 | status_code: '400' 16 | message: Bad Request 17 | explanation: Bad request syntax or unsupported method 18 | headers: 19 | status: 'HTTP/2 400 ' 20 | content-encoding: gzip 21 | content-type: application/json 22 | server: Caddy 23 | vary: Accept-Encoding 24 | x-content-type-options: nosniff 25 | content-length: '81' 26 | date: Tue, 19 May 2020 21:00:14 GMT 27 | body: 28 | encoding: UTF-8 29 | file: no 30 | string: '{"error":{"message":"rule 578999 not found"},"data":null}' 31 | recorded_at: 2020-05-19 21:00:14 GMT 32 | recorded_with: vcr/0.5.4, webmockr/0.6.2 33 | -------------------------------------------------------------------------------- /tests/fixtures/cchn_pkg_rule_get_one_rule.yml: -------------------------------------------------------------------------------- 1 | http_interactions: 2 | - request: 3 | method: get 4 | uri: https://cranchecks.info/notifications/rules?package=honeybadger 5 | body: 6 | encoding: '' 7 | string: '' 8 | headers: 9 | User-Agent: r-curl/4.3 crul/0.9.0 rOpenSci(cchecks/0.1.5.95) 10 | Accept-Encoding: gzip, deflate 11 | Accept: application/json, text/xml, application/xml, */* 12 | Authorization: Bearer <> 13 | response: 14 | status: 15 | status_code: '200' 16 | message: OK 17 | explanation: Request fulfilled, document follows 18 | headers: 19 | status: 'HTTP/2 200 ' 20 | content-encoding: gzip 21 | content-type: text/html;charset=utf-8 22 | server: Caddy 23 | vary: Accept-Encoding 24 | x-content-type-options: nosniff 25 | x-frame-options: SAMEORIGIN 26 | x-xss-protection: 1; mode=block 27 | content-length: '124' 28 | date: Tue, 19 May 2020 21:00:15 GMT 29 | body: 30 | encoding: UTF-8 31 | file: no 32 | string: '{"error":null,"data":[{"id":247,"package":"honeybadger","rule_status":"warn","rule_time":6,"rule_platforms":null,"rule_regex":null}]}' 33 | recorded_at: 2020-05-19 21:00:15 GMT 34 | recorded_with: vcr/0.5.4, webmockr/0.6.2 35 | - request: 36 | method: get 37 | uri: https://cranchecks.info/notifications/rules/247 38 | body: 39 | encoding: '' 40 | string: '' 41 | headers: 42 | User-Agent: r-curl/4.3 crul/0.9.0 rOpenSci(cchecks/0.1.5.95) 43 | Accept-Encoding: gzip, deflate 44 | Accept: application/json, text/xml, application/xml, */* 45 | Authorization: Bearer <> 46 | response: 47 | status: 48 | status_code: '200' 49 | message: OK 50 | explanation: Request fulfilled, document follows 51 | headers: 52 | status: 'HTTP/2 200 ' 53 | content-encoding: gzip 54 | content-type: text/html;charset=utf-8 55 | server: Caddy 56 | vary: Accept-Encoding 57 | x-content-type-options: nosniff 58 | x-frame-options: SAMEORIGIN 59 | x-xss-protection: 1; mode=block 60 | content-length: '121' 61 | date: Tue, 19 May 2020 21:00:15 GMT 62 | body: 63 | encoding: UTF-8 64 | file: no 65 | string: '{"error":null,"data":{"id":247,"package":"honeybadger","rule_status":"warn","rule_time":6,"rule_platforms":null,"rule_regex":null}}' 66 | recorded_at: 2020-05-19 21:00:15 GMT 67 | recorded_with: vcr/0.5.4, webmockr/0.6.2 68 | -------------------------------------------------------------------------------- /tests/fixtures/cchn_pkg_rule_list_add_rule.yml: -------------------------------------------------------------------------------- 1 | http_interactions: 2 | - request: 3 | method: post 4 | uri: https://cranchecks.info/notifications/rules 5 | body: 6 | encoding: '' 7 | string: '[{"package":"rgbif","status":"note"}]' 8 | headers: 9 | User-Agent: r-curl/4.3 crul/0.9.0 rOpenSci(cchecks/0.1.5.95) 10 | Accept-Encoding: gzip, deflate 11 | Accept: application/json, text/xml, application/xml, */* 12 | Authorization: Bearer <> 13 | Content-Type: application/json 14 | response: 15 | status: 16 | status_code: '200' 17 | message: OK 18 | explanation: Request fulfilled, document follows 19 | headers: 20 | status: 'HTTP/2 200 ' 21 | access-control-allow-methods: POST 22 | access-control-allow-origin: '*' 23 | cache-control: public, must-revalidate, max-age=60 24 | content-encoding: gzip 25 | content-type: application/json; charset=utf8 26 | server: Caddy 27 | vary: Accept-Encoding 28 | x-content-type-options: nosniff 29 | content-length: '55' 30 | date: Tue, 19 May 2020 20:03:44 GMT 31 | body: 32 | encoding: UTF-8 33 | file: no 34 | string: '{"error":null,"data":"success"}' 35 | recorded_at: 2020-05-19 20:03:44 GMT 36 | recorded_with: vcr/0.5.4, webmockr/0.6.2 37 | -------------------------------------------------------------------------------- /tests/fixtures/cchn_pkg_rule_list_cleanup.yml: -------------------------------------------------------------------------------- 1 | http_interactions: 2 | - request: 3 | method: delete 4 | uri: https://cranchecks.info/notifications/rules/241 5 | body: 6 | encoding: '' 7 | string: '' 8 | headers: 9 | User-Agent: r-curl/4.3 crul/0.9.0 rOpenSci(cchecks/0.1.5.95) 10 | Accept-Encoding: gzip, deflate 11 | Accept: application/json, text/xml, application/xml, */* 12 | Authorization: Bearer <> 13 | response: 14 | status: 15 | status_code: '204' 16 | message: No Content 17 | explanation: Request fulfilled, nothing follows 18 | headers: 19 | status: 'HTTP/2 204 ' 20 | access-control-allow-methods: DELETE 21 | content-encoding: gzip 22 | server: Caddy 23 | vary: Accept-Encoding 24 | x-content-type-options: nosniff 25 | date: Tue, 19 May 2020 20:01:33 GMT 26 | body: 27 | encoding: UTF-8 28 | file: no 29 | string: '' 30 | recorded_at: 2020-05-19 20:01:33 GMT 31 | recorded_with: vcr/0.5.4, webmockr/0.6.2 32 | -------------------------------------------------------------------------------- /tests/fixtures/cchn_pkg_rule_list_empty.yml: -------------------------------------------------------------------------------- 1 | http_interactions: 2 | - request: 3 | method: get 4 | uri: https://cranchecks.info/notifications/rules?package=rgbif 5 | body: 6 | encoding: '' 7 | string: '' 8 | headers: 9 | User-Agent: r-curl/4.3 crul/0.9.0 rOpenSci(cchecks/0.1.5.95) 10 | Accept-Encoding: gzip, deflate 11 | Accept: application/json, text/xml, application/xml, */* 12 | Authorization: Bearer <> 13 | response: 14 | status: 15 | status_code: '200' 16 | message: OK 17 | explanation: Request fulfilled, document follows 18 | headers: 19 | status: 'HTTP/2 200 ' 20 | content-encoding: gzip 21 | content-type: text/html;charset=utf-8 22 | server: Caddy 23 | vary: Accept-Encoding 24 | x-content-type-options: nosniff 25 | x-frame-options: SAMEORIGIN 26 | x-xss-protection: 1; mode=block 27 | content-length: '48' 28 | date: Tue, 19 May 2020 20:01:32 GMT 29 | body: 30 | encoding: UTF-8 31 | file: no 32 | string: '{"error":null,"data":[]}' 33 | recorded_at: 2020-05-19 20:01:32 GMT 34 | recorded_with: vcr/0.5.4, webmockr/0.6.2 35 | -------------------------------------------------------------------------------- /tests/fixtures/cchn_pkg_rule_list_one_rule.yml: -------------------------------------------------------------------------------- 1 | http_interactions: 2 | - request: 3 | method: get 4 | uri: https://cranchecks.info/notifications/rules?package=rgbif 5 | body: 6 | encoding: '' 7 | string: '' 8 | headers: 9 | User-Agent: r-curl/4.3 crul/0.9.0 rOpenSci(cchecks/0.1.5.95) 10 | Accept-Encoding: gzip, deflate 11 | Accept: application/json, text/xml, application/xml, */* 12 | Authorization: Bearer <> 13 | response: 14 | status: 15 | status_code: '200' 16 | message: OK 17 | explanation: Request fulfilled, document follows 18 | headers: 19 | status: 'HTTP/2 200 ' 20 | content-encoding: gzip 21 | content-type: text/html;charset=utf-8 22 | server: Caddy 23 | vary: Accept-Encoding 24 | x-content-type-options: nosniff 25 | x-frame-options: SAMEORIGIN 26 | x-xss-protection: 1; mode=block 27 | content-length: '120' 28 | date: Tue, 19 May 2020 20:01:33 GMT 29 | body: 30 | encoding: UTF-8 31 | file: no 32 | string: '{"error":null,"data":[{"id":241,"package":"cchecks","rule_status":"note","rule_time":null,"rule_platforms":null,"rule_regex":null}]}' 33 | recorded_at: 2020-05-19 20:01:33 GMT 34 | recorded_with: vcr/0.5.4, webmockr/0.6.2 35 | -------------------------------------------------------------------------------- /tests/fixtures/cchn_rule_add.yml: -------------------------------------------------------------------------------- 1 | http_interactions: 2 | - request: 3 | method: post 4 | uri: https://cranchecks.info/notifications/rules 5 | body: 6 | encoding: '' 7 | string: '[{"package":"testing123","status":"warn","platforms":2}]' 8 | headers: 9 | User-Agent: r-curl/4.3 crul/0.9.0 rOpenSci(cchecks/0.1.8.94) 10 | Accept-Encoding: gzip, deflate 11 | Accept: application/json, text/xml, application/xml, */* 12 | Authorization: Bearer <> 13 | Content-Type: application/json 14 | response: 15 | status: 16 | status_code: '200' 17 | message: OK 18 | explanation: Request fulfilled, document follows 19 | headers: 20 | status: 'HTTP/2 200 ' 21 | access-control-allow-methods: POST 22 | access-control-allow-origin: '*' 23 | cache-control: public, must-revalidate, max-age=60 24 | content-type: application/json; charset=utf8 25 | server: Caddy 26 | x-content-type-options: nosniff 27 | content-length: '124' 28 | date: Fri, 22 May 2020 20:56:34 GMT 29 | body: 30 | encoding: UTF-8 31 | file: no 32 | string: '{"error":null,"data":[{"id":282,"already_existed":false,"rule":"package:testing123, 33 | status:warn, flavor:2, time:, regex:"}]}' 34 | recorded_at: 2020-05-22 20:56:34 GMT 35 | recorded_with: vcr/0.5.4, webmockr/0.6.2 36 | - request: 37 | method: get 38 | uri: https://cranchecks.info/notifications/rules 39 | body: 40 | encoding: '' 41 | string: '' 42 | headers: 43 | User-Agent: r-curl/4.3 crul/0.9.0 rOpenSci(cchecks/0.1.8.94) 44 | Accept-Encoding: gzip, deflate 45 | Accept: application/json, text/xml, application/xml, */* 46 | Authorization: Bearer <> 47 | response: 48 | status: 49 | status_code: '200' 50 | message: OK 51 | explanation: Request fulfilled, document follows 52 | headers: 53 | status: 'HTTP/2 200 ' 54 | content-encoding: gzip 55 | content-type: text/html;charset=utf-8 56 | server: Caddy 57 | vary: Accept-Encoding 58 | x-content-type-options: nosniff 59 | x-frame-options: SAMEORIGIN 60 | x-xss-protection: 1; mode=block 61 | content-length: '192' 62 | date: Fri, 22 May 2020 20:56:34 GMT 63 | body: 64 | encoding: UTF-8 65 | file: no 66 | string: '{"error":null,"data":[{"id":242,"package":"rgbif","rule_status":"note","rule_time":null,"rule_platforms":null,"rule_regex":null},{"id":279,"package":"bubbles","rule_status":"note","rule_time":null,"rule_platforms":"3","rule_regex":null},{"id":280,"package":"testing456","rule_status":"warn","rule_time":null,"rule_platforms":null,"rule_regex":null},{"id":281,"package":"testing456","rule_status":"error","rule_time":4,"rule_platforms":null,"rule_regex":null},{"id":282,"package":"testing123","rule_status":"warn","rule_time":null,"rule_platforms":"2","rule_regex":null}]}' 67 | recorded_at: 2020-05-22 20:56:34 GMT 68 | recorded_with: vcr/0.5.4, webmockr/0.6.2 69 | -------------------------------------------------------------------------------- /tests/fixtures/cchn_rule_add_cleanup.yml: -------------------------------------------------------------------------------- 1 | http_interactions: 2 | - request: 3 | method: delete 4 | uri: https://cranchecks.info/notifications/rules/282 5 | body: 6 | encoding: '' 7 | string: '' 8 | headers: 9 | User-Agent: r-curl/4.3 crul/0.9.0 rOpenSci(cchecks/0.1.8.94) 10 | Accept-Encoding: gzip, deflate 11 | Accept: application/json, text/xml, application/xml, */* 12 | Authorization: Bearer <> 13 | response: 14 | status: 15 | status_code: '204' 16 | message: No Content 17 | explanation: Request fulfilled, nothing follows 18 | headers: 19 | status: 'HTTP/2 204 ' 20 | access-control-allow-methods: DELETE 21 | server: Caddy 22 | x-content-type-options: nosniff 23 | date: Fri, 22 May 2020 20:57:08 GMT 24 | body: 25 | encoding: UTF-8 26 | file: no 27 | string: '' 28 | recorded_at: 2020-05-22 20:57:08 GMT 29 | recorded_with: vcr/0.5.4, webmockr/0.6.2 30 | -------------------------------------------------------------------------------- /tests/fixtures/cchn_rule_get_add_rule.yml: -------------------------------------------------------------------------------- 1 | http_interactions: 2 | - request: 3 | method: post 4 | uri: https://cranchecks.info/notifications/rules 5 | body: 6 | encoding: '' 7 | string: '[{"package":"honeybadger","status":"warn","time":6}]' 8 | headers: 9 | User-Agent: r-curl/4.3 crul/0.9.0 rOpenSci(cchecks/0.1.4.91) 10 | Accept-Encoding: gzip, deflate 11 | Accept: application/json, text/xml, application/xml, */* 12 | Authorization: Bearer <> 13 | Content-Type: application/json 14 | response: 15 | status: 16 | status_code: '200' 17 | message: OK 18 | explanation: Request fulfilled, document follows 19 | headers: 20 | status: 'HTTP/2 200 ' 21 | access-control-allow-methods: POST 22 | access-control-allow-origin: '*' 23 | cache-control: public, must-revalidate, max-age=60 24 | content-encoding: gzip 25 | content-type: application/json; charset=utf8 26 | server: Caddy 27 | vary: Accept-Encoding 28 | x-content-type-options: nosniff 29 | content-length: '55' 30 | date: Mon, 11 May 2020 23:01:13 GMT 31 | body: 32 | encoding: UTF-8 33 | file: no 34 | string: '{"error":null,"data":"success"}' 35 | recorded_at: 2020-05-11 23:01:13 GMT 36 | recorded_with: vcr/0.5.4, webmockr/0.6.2.92 37 | -------------------------------------------------------------------------------- /tests/fixtures/cchn_rule_get_cleanup.yml: -------------------------------------------------------------------------------- 1 | http_interactions: 2 | - request: 3 | method: delete 4 | uri: https://cranchecks.info/notifications/rules/111 5 | body: 6 | encoding: '' 7 | string: '' 8 | headers: 9 | User-Agent: r-curl/4.3 crul/0.9.0 rOpenSci(cchecks/0.1.4.91) 10 | Accept-Encoding: gzip, deflate 11 | Accept: application/json, text/xml, application/xml, */* 12 | Authorization: Bearer <> 13 | response: 14 | status: 15 | status_code: '204' 16 | message: No Content 17 | explanation: Request fulfilled, nothing follows 18 | headers: 19 | status: 'HTTP/2 204 ' 20 | access-control-allow-methods: DELETE 21 | content-encoding: gzip 22 | server: Caddy 23 | vary: Accept-Encoding 24 | x-content-type-options: nosniff 25 | date: Mon, 11 May 2020 23:01:14 GMT 26 | body: 27 | encoding: UTF-8 28 | file: no 29 | string: '' 30 | recorded_at: 2020-05-11 23:01:14 GMT 31 | recorded_with: vcr/0.5.4, webmockr/0.6.2.92 32 | -------------------------------------------------------------------------------- /tests/fixtures/cchn_rule_get_empty_rule_list.yml: -------------------------------------------------------------------------------- 1 | http_interactions: 2 | - request: 3 | method: get 4 | uri: https://cranchecks.info/notifications/rules 5 | body: 6 | encoding: '' 7 | string: '' 8 | headers: 9 | User-Agent: r-curl/4.3 crul/0.9.0 rOpenSci(cchecks/0.1.5.93) 10 | Accept-Encoding: gzip, deflate 11 | Accept: application/json, text/xml, application/xml, */* 12 | Authorization: Bearer <> 13 | response: 14 | status: 15 | status_code: '200' 16 | message: OK 17 | explanation: Request fulfilled, document follows 18 | headers: 19 | status: 'HTTP/2 200 ' 20 | content-encoding: gzip 21 | content-type: text/html;charset=utf-8 22 | server: Caddy 23 | vary: Accept-Encoding 24 | x-content-type-options: nosniff 25 | x-frame-options: SAMEORIGIN 26 | x-xss-protection: 1; mode=block 27 | content-length: '48' 28 | date: Tue, 12 May 2020 14:59:45 GMT 29 | body: 30 | encoding: UTF-8 31 | file: no 32 | string: '{"error":null,"data":[]}' 33 | recorded_at: 2020-05-12 14:59:45 GMT 34 | recorded_with: vcr/0.5.4, webmockr/0.6.2.92 35 | -------------------------------------------------------------------------------- /tests/fixtures/cchn_rule_get_not_found.yml: -------------------------------------------------------------------------------- 1 | http_interactions: 2 | - request: 3 | method: get 4 | uri: https://cranchecks.info/notifications/rules/578999 5 | body: 6 | encoding: '' 7 | string: '' 8 | headers: 9 | User-Agent: r-curl/4.3 crul/0.9.0 rOpenSci(cchecks/0.1.4.91) 10 | Accept-Encoding: gzip, deflate 11 | Accept: application/json, text/xml, application/xml, */* 12 | Authorization: Bearer <> 13 | response: 14 | status: 15 | status_code: '400' 16 | message: Bad Request 17 | explanation: Bad request syntax or unsupported method 18 | headers: 19 | status: 'HTTP/2 400 ' 20 | content-encoding: gzip 21 | content-type: application/json 22 | server: Caddy 23 | vary: Accept-Encoding 24 | x-content-type-options: nosniff 25 | content-length: '81' 26 | date: Mon, 11 May 2020 23:01:13 GMT 27 | body: 28 | encoding: UTF-8 29 | file: no 30 | string: '{"error":{"message":"rule 578999 not found"},"data":null}' 31 | recorded_at: 2020-05-11 23:01:13 GMT 32 | recorded_with: vcr/0.5.4, webmockr/0.6.2.92 33 | -------------------------------------------------------------------------------- /tests/fixtures/cchn_rule_get_one_rule.yml: -------------------------------------------------------------------------------- 1 | http_interactions: 2 | - request: 3 | method: get 4 | uri: https://cranchecks.info/notifications/rules 5 | body: 6 | encoding: '' 7 | string: '' 8 | headers: 9 | User-Agent: r-curl/4.3 crul/0.9.0 rOpenSci(cchecks/0.1.4.91) 10 | Accept-Encoding: gzip, deflate 11 | Accept: application/json, text/xml, application/xml, */* 12 | Authorization: Bearer <> 13 | response: 14 | status: 15 | status_code: '200' 16 | message: OK 17 | explanation: Request fulfilled, document follows 18 | headers: 19 | status: 'HTTP/2 200 ' 20 | content-encoding: gzip 21 | content-type: text/html;charset=utf-8 22 | server: Caddy 23 | vary: Accept-Encoding 24 | x-content-type-options: nosniff 25 | x-frame-options: SAMEORIGIN 26 | x-xss-protection: 1; mode=block 27 | content-length: '124' 28 | date: Mon, 11 May 2020 23:01:13 GMT 29 | body: 30 | encoding: UTF-8 31 | file: no 32 | string: '{"error":null,"data":[{"id":111,"package":"honeybadger","rule_status":"warn","rule_time":6,"rule_platforms":null,"rule_regex":null}]}' 33 | recorded_at: 2020-05-11 23:01:14 GMT 34 | recorded_with: vcr/0.5.4, webmockr/0.6.2.92 35 | - request: 36 | method: get 37 | uri: https://cranchecks.info/notifications/rules/111 38 | body: 39 | encoding: '' 40 | string: '' 41 | headers: 42 | User-Agent: r-curl/4.3 crul/0.9.0 rOpenSci(cchecks/0.1.4.91) 43 | Accept-Encoding: gzip, deflate 44 | Accept: application/json, text/xml, application/xml, */* 45 | Authorization: Bearer <> 46 | response: 47 | status: 48 | status_code: '200' 49 | message: OK 50 | explanation: Request fulfilled, document follows 51 | headers: 52 | status: 'HTTP/2 200 ' 53 | content-encoding: gzip 54 | content-type: text/html;charset=utf-8 55 | server: Caddy 56 | vary: Accept-Encoding 57 | x-content-type-options: nosniff 58 | x-frame-options: SAMEORIGIN 59 | x-xss-protection: 1; mode=block 60 | content-length: '120' 61 | date: Mon, 11 May 2020 23:01:14 GMT 62 | body: 63 | encoding: UTF-8 64 | file: no 65 | string: '{"error":null,"data":{"id":111,"package":"honeybadger","rule_status":"warn","rule_time":6,"rule_platforms":null,"rule_regex":null}}' 66 | recorded_at: 2020-05-11 23:01:14 GMT 67 | recorded_with: vcr/0.5.4, webmockr/0.6.2.92 68 | -------------------------------------------------------------------------------- /tests/fixtures/cchn_rule_list_add_rule.yml: -------------------------------------------------------------------------------- 1 | http_interactions: 2 | - request: 3 | method: post 4 | uri: https://cranchecks.info/notifications/rules 5 | body: 6 | encoding: '' 7 | string: '[{"package":"wombat","status":"note"}]' 8 | headers: 9 | User-Agent: r-curl/4.3 crul/0.9.0 rOpenSci(cchecks/0.1.4.91) 10 | Accept-Encoding: gzip, deflate 11 | Accept: application/json, text/xml, application/xml, */* 12 | Authorization: Bearer <> 13 | Content-Type: application/json 14 | response: 15 | status: 16 | status_code: '200' 17 | message: OK 18 | explanation: Request fulfilled, document follows 19 | headers: 20 | status: 'HTTP/2 200 ' 21 | access-control-allow-methods: POST 22 | access-control-allow-origin: '*' 23 | cache-control: public, must-revalidate, max-age=60 24 | content-encoding: gzip 25 | content-type: application/json; charset=utf8 26 | server: Caddy 27 | vary: Accept-Encoding 28 | x-content-type-options: nosniff 29 | content-length: '55' 30 | date: Mon, 11 May 2020 22:35:42 GMT 31 | body: 32 | encoding: UTF-8 33 | file: no 34 | string: '{"error":null,"data":"success"}' 35 | recorded_at: 2020-05-11 22:35:42 GMT 36 | recorded_with: vcr/0.5.4, webmockr/0.6.2.92 37 | -------------------------------------------------------------------------------- /tests/fixtures/cchn_rule_list_cleanup.yml: -------------------------------------------------------------------------------- 1 | http_interactions: 2 | - request: 3 | method: delete 4 | uri: https://cranchecks.info/notifications/rules/110 5 | body: 6 | encoding: '' 7 | string: '' 8 | headers: 9 | User-Agent: r-curl/4.3 crul/0.9.0 rOpenSci(cchecks/0.1.4.91) 10 | Accept-Encoding: gzip, deflate 11 | Accept: application/json, text/xml, application/xml, */* 12 | Authorization: Bearer <> 13 | response: 14 | status: 15 | status_code: '204' 16 | message: No Content 17 | explanation: Request fulfilled, nothing follows 18 | headers: 19 | status: 'HTTP/2 204 ' 20 | access-control-allow-methods: DELETE 21 | content-encoding: gzip 22 | server: Caddy 23 | vary: Accept-Encoding 24 | x-content-type-options: nosniff 25 | date: Mon, 11 May 2020 22:35:42 GMT 26 | body: 27 | encoding: UTF-8 28 | file: no 29 | string: '' 30 | recorded_at: 2020-05-11 22:35:42 GMT 31 | recorded_with: vcr/0.5.4, webmockr/0.6.2.92 32 | -------------------------------------------------------------------------------- /tests/fixtures/cchn_rule_list_empty.yml: -------------------------------------------------------------------------------- 1 | http_interactions: 2 | - request: 3 | method: get 4 | uri: https://cranchecks.info/notifications/rules 5 | body: 6 | encoding: '' 7 | string: '' 8 | headers: 9 | User-Agent: r-curl/4.3 crul/0.9.0 rOpenSci(cchecks/0.1.4.91) 10 | Accept-Encoding: gzip, deflate 11 | Accept: application/json, text/xml, application/xml, */* 12 | Authorization: Bearer <> 13 | response: 14 | status: 15 | status_code: '200' 16 | message: OK 17 | explanation: Request fulfilled, document follows 18 | headers: 19 | status: 'HTTP/2 200 ' 20 | content-encoding: gzip 21 | content-type: text/html;charset=utf-8 22 | server: Caddy 23 | vary: Accept-Encoding 24 | x-content-type-options: nosniff 25 | x-frame-options: SAMEORIGIN 26 | x-xss-protection: 1; mode=block 27 | content-length: '48' 28 | date: Mon, 11 May 2020 22:35:42 GMT 29 | body: 30 | encoding: UTF-8 31 | file: no 32 | string: '{"error":null,"data":[]}' 33 | recorded_at: 2020-05-11 22:35:42 GMT 34 | recorded_with: vcr/0.5.4, webmockr/0.6.2.92 35 | -------------------------------------------------------------------------------- /tests/fixtures/cchn_rule_list_one_rule.yml: -------------------------------------------------------------------------------- 1 | http_interactions: 2 | - request: 3 | method: get 4 | uri: https://cranchecks.info/notifications/rules 5 | body: 6 | encoding: '' 7 | string: '' 8 | headers: 9 | User-Agent: r-curl/4.3 crul/0.9.0 rOpenSci(cchecks/0.1.4.91) 10 | Accept-Encoding: gzip, deflate 11 | Accept: application/json, text/xml, application/xml, */* 12 | Authorization: Bearer <> 13 | response: 14 | status: 15 | status_code: '200' 16 | message: OK 17 | explanation: Request fulfilled, document follows 18 | headers: 19 | status: 'HTTP/2 200 ' 20 | content-encoding: gzip 21 | content-type: text/html;charset=utf-8 22 | server: Caddy 23 | vary: Accept-Encoding 24 | x-content-type-options: nosniff 25 | x-frame-options: SAMEORIGIN 26 | x-xss-protection: 1; mode=block 27 | content-length: '118' 28 | date: Mon, 11 May 2020 22:35:42 GMT 29 | body: 30 | encoding: UTF-8 31 | file: no 32 | string: '{"error":null,"data":[{"id":110,"package":"wombat","rule_status":"note","rule_time":null,"rule_platforms":null,"rule_regex":null}]}' 33 | recorded_at: 2020-05-11 22:35:42 GMT 34 | recorded_with: vcr/0.5.4, webmockr/0.6.2.92 35 | -------------------------------------------------------------------------------- /tests/fixtures/cchn_rules_add.yml: -------------------------------------------------------------------------------- 1 | http_interactions: 2 | - request: 3 | method: post 4 | uri: https://cranchecks.info/notifications/rules 5 | body: 6 | encoding: '' 7 | string: '[{"package":"testing456","status":"warn"},{"package":"testing456","status":"error","time":4}]' 8 | headers: 9 | User-Agent: r-curl/4.3 crul/0.9.0 rOpenSci(cchecks/0.1.8.94) 10 | Accept-Encoding: gzip, deflate 11 | Accept: application/json, text/xml, application/xml, */* 12 | Authorization: Bearer <> 13 | Content-Type: application/json 14 | response: 15 | status: 16 | status_code: '200' 17 | message: OK 18 | explanation: Request fulfilled, document follows 19 | headers: 20 | status: 'HTTP/2 200 ' 21 | access-control-allow-methods: POST 22 | access-control-allow-origin: '*' 23 | cache-control: public, must-revalidate, max-age=60 24 | content-type: application/json; charset=utf8 25 | server: Caddy 26 | x-content-type-options: nosniff 27 | content-length: '223' 28 | date: Fri, 22 May 2020 20:56:38 GMT 29 | body: 30 | encoding: UTF-8 31 | file: no 32 | string: '{"error":null,"data":[{"id":280,"already_existed":true,"rule":"package:testing456, 33 | status:warn, flavor:, time:, regex:"},{"id":281,"already_existed":true,"rule":"package:testing456, 34 | status:error, flavor:, time:4, regex:"}]}' 35 | recorded_at: 2020-05-22 20:56:38 GMT 36 | recorded_with: vcr/0.5.4, webmockr/0.6.2 37 | - request: 38 | method: get 39 | uri: https://cranchecks.info/notifications/rules 40 | body: 41 | encoding: '' 42 | string: '' 43 | headers: 44 | User-Agent: r-curl/4.3 crul/0.9.0 rOpenSci(cchecks/0.1.8.94) 45 | Accept-Encoding: gzip, deflate 46 | Accept: application/json, text/xml, application/xml, */* 47 | Authorization: Bearer <> 48 | response: 49 | status: 50 | status_code: '200' 51 | message: OK 52 | explanation: Request fulfilled, document follows 53 | headers: 54 | status: 'HTTP/2 200 ' 55 | content-encoding: gzip 56 | content-type: text/html;charset=utf-8 57 | server: Caddy 58 | vary: Accept-Encoding 59 | x-content-type-options: nosniff 60 | x-frame-options: SAMEORIGIN 61 | x-xss-protection: 1; mode=block 62 | content-length: '192' 63 | date: Fri, 22 May 2020 20:56:38 GMT 64 | body: 65 | encoding: UTF-8 66 | file: no 67 | string: '{"error":null,"data":[{"id":242,"package":"rgbif","rule_status":"note","rule_time":null,"rule_platforms":null,"rule_regex":null},{"id":279,"package":"bubbles","rule_status":"note","rule_time":null,"rule_platforms":"3","rule_regex":null},{"id":280,"package":"testing456","rule_status":"warn","rule_time":null,"rule_platforms":null,"rule_regex":null},{"id":281,"package":"testing456","rule_status":"error","rule_time":4,"rule_platforms":null,"rule_regex":null},{"id":282,"package":"testing123","rule_status":"warn","rule_time":null,"rule_platforms":"2","rule_regex":null}]}' 68 | recorded_at: 2020-05-22 20:56:38 GMT 69 | recorded_with: vcr/0.5.4, webmockr/0.6.2 70 | -------------------------------------------------------------------------------- /tests/fixtures/cchn_rules_add_cleanup.yml: -------------------------------------------------------------------------------- 1 | http_interactions: 2 | - request: 3 | method: delete 4 | uri: https://cranchecks.info/notifications/rules/280 5 | body: 6 | encoding: '' 7 | string: '' 8 | headers: 9 | User-Agent: r-curl/4.3 crul/0.9.0 rOpenSci(cchecks/0.1.8.94) 10 | Accept-Encoding: gzip, deflate 11 | Accept: application/json, text/xml, application/xml, */* 12 | Authorization: Bearer <> 13 | response: 14 | status: 15 | status_code: '204' 16 | message: No Content 17 | explanation: Request fulfilled, nothing follows 18 | headers: 19 | status: 'HTTP/2 204 ' 20 | access-control-allow-methods: DELETE 21 | server: Caddy 22 | x-content-type-options: nosniff 23 | date: Fri, 22 May 2020 20:57:11 GMT 24 | body: 25 | encoding: UTF-8 26 | file: no 27 | string: '' 28 | recorded_at: 2020-05-22 20:57:11 GMT 29 | recorded_with: vcr/0.5.4, webmockr/0.6.2 30 | - request: 31 | method: delete 32 | uri: https://cranchecks.info/notifications/rules/281 33 | body: 34 | encoding: '' 35 | string: '' 36 | headers: 37 | User-Agent: r-curl/4.3 crul/0.9.0 rOpenSci(cchecks/0.1.8.94) 38 | Accept-Encoding: gzip, deflate 39 | Accept: application/json, text/xml, application/xml, */* 40 | Authorization: Bearer <> 41 | response: 42 | status: 43 | status_code: '204' 44 | message: No Content 45 | explanation: Request fulfilled, nothing follows 46 | headers: 47 | status: 'HTTP/2 204 ' 48 | access-control-allow-methods: DELETE 49 | server: Caddy 50 | x-content-type-options: nosniff 51 | date: Fri, 22 May 2020 20:57:11 GMT 52 | body: 53 | encoding: UTF-8 54 | file: no 55 | string: '' 56 | recorded_at: 2020-05-22 20:57:11 GMT 57 | recorded_with: vcr/0.5.4, webmockr/0.6.2 58 | -------------------------------------------------------------------------------- /tests/testthat.R: -------------------------------------------------------------------------------- 1 | library(testthat) 2 | library(cchecks) 3 | 4 | test_check("cchecks") 5 | -------------------------------------------------------------------------------- /tests/testthat/helper-cchecks.R: -------------------------------------------------------------------------------- 1 | on_ci <- isTRUE(as.logical(Sys.getenv("CI"))) 2 | Sys.setenv(CCHECKS_TESTING = on_ci) 3 | path <- file.path(tempfile(), "emails.csv") 4 | Sys.setenv(CCHECKS_TESTING_EMAIL_FILE_PATH = path) 5 | # Sys.setenv(CCHECKS_TOKEN_SCKOTT7 = "stuff") 6 | # Sys.setenv(CCHECKS_TOKEN_MYRMECOCYSTUS = "things") 7 | if (on_ci && !file.exists(path)) { 8 | z <- data.frame( 9 | V1 = c("sckott7@gmail.com", "myrmecocystus@gmail.com"), 10 | V2 = c(Sys.getenv("CCHECKS_TOKEN_SCKOTT7"), 11 | Sys.getenv("CCHECKS_TOKEN_MYRMECOCYSTUS")) 12 | ) 13 | parent <- dirname(path) 14 | if (!file.exists(parent)) dir.create(parent, recursive = TRUE) 15 | utils::write.table(z, file = path, sep = ",", col.names = FALSE, 16 | row.names = FALSE) 17 | } 18 | 19 | library("vcr") 20 | vcr::vcr_configure( 21 | dir = "../fixtures", 22 | filter_sensitive_data = list( 23 | "<>" = email_get_token("sckott7@gmail.com"), 24 | "<>" = email_get_token("myrmecocystus@gmail.com") 25 | ) 26 | ) 27 | vcr::check_cassette_names() 28 | 29 | # name = "foobar" 30 | fake_pkg <- function(name) { 31 | stopifnot(is.character(name)) 32 | path <- file.path(tempdir(), name) 33 | fields <- list( 34 | `Authors@R` = 'person("Jane", "Doe", email = "sckott7@gmail.com", role = c("aut", "cre"))' 35 | ) 36 | usethis::create_package(path, fields = fields, open = FALSE) 37 | return(path) 38 | } 39 | -------------------------------------------------------------------------------- /tests/testthat/test-cch_heartbeat.R: -------------------------------------------------------------------------------- 1 | test_that("cch_heartbeat", { 2 | vcr::use_cassette("cch_heartbeat", { 3 | aa <- cch_heartbeat() 4 | }) 5 | 6 | expect_is(aa, "list") 7 | expect_named(aa, "routes") 8 | expect_is(aa$routes, "character") 9 | expect_true(all(grepl("/", aa$routes))) 10 | }) 11 | -------------------------------------------------------------------------------- /tests/testthat/test-cch_history.R: -------------------------------------------------------------------------------- 1 | test_that("cch_history fails well", { 2 | vcr::use_cassette("cch_history_error", { 3 | expect_error(cch_history(5), "class character") 4 | expect_error(cch_history("2030-05-22"), "`date` not found") 5 | }) 6 | }) 7 | 8 | # FIXME: the on.exit() delete the file cleans up the cached file 9 | # in the test - so on subsequent runs this test cant find the file 10 | # Not sure how to handle this? 11 | # test_that("cch_history", { 12 | # vcr::use_cassette("cch_history", { 13 | # aa <- cch_history("2020-02-22") 14 | # }) 15 | # expect_is(aa, "data.frame") 16 | # for (i in names(aa)) expect_is(aa[[i]], "character") 17 | # expect_gt(NROW(aa), 12000L) 18 | # expect_is(aa$summary[1], "character") 19 | # expect_is(jsonlite::fromJSON(aa$summary[1]), "list") 20 | # }) 21 | -------------------------------------------------------------------------------- /tests/testthat/test-cch_maintainers.R: -------------------------------------------------------------------------------- 1 | test_that("cch_maintainers fails well", { 2 | vcr::use_cassette("cch_maintainers_error", { 3 | expect_error(cch_maintainers(limit = "foo"), "limit is not an integer") 4 | expect_error(cch_maintainers(offset = "bar"), "offset is not an integer") 5 | expect_error(cch_maintainers(x = "aaaaaaaaaaa"), "no results found") 6 | }) 7 | }) 8 | 9 | test_that("cch_maintainers", { 10 | email <- "csardi.gabor_at_gmail.com" 11 | 12 | vcr::use_cassette("cch_maintainers_one_maint", { 13 | aa <- cch_maintainers(email) 14 | }) 15 | 16 | expect_is(aa, "list") 17 | expect_named(aa) 18 | expect_null(aa$error) 19 | expect_is(aa$data, "list") 20 | expect_is(aa$data$email, "character") 21 | expect_equal(aa$data$email, email) 22 | expect_is(aa$data$name, "character") 23 | expect_is(aa$data$url, "character") 24 | expect_is(aa$data$table, "data.frame") 25 | expect_is(aa$data$packages, "data.frame") 26 | expect_is(aa$data$date_updated, "character") 27 | 28 | vcr::use_cassette("cch_maintainers_all_maints", { 29 | cc <- cch_maintainers() 30 | }) 31 | 32 | expect_is(cc, "list") 33 | expect_named(cc) 34 | expect_is(cc$data, "data.frame") 35 | expect_is(cc$data$table, "list") 36 | expect_is(cc$data$packages, "list") 37 | }) 38 | -------------------------------------------------------------------------------- /tests/testthat/test-cch_pkgs.R: -------------------------------------------------------------------------------- 1 | test_that("cch_pkgs fails well", { 2 | vcr::use_cassette("cch_pkgs_error", { 3 | expect_error(cch_pkgs(limit = "foo"), "limit is not an integer") 4 | expect_error(cch_pkgs(offset = "bar"), "offset is not an integer") 5 | expect_error(cch_pkgs(x = "aaaaaaaaaaa"), "no results found") 6 | }) 7 | }) 8 | 9 | test_that("cch_pkgs", { 10 | vcr::use_cassette("cch_pkgs_one_pkg", { 11 | aa <- cch_pkgs("worrms") 12 | }) 13 | 14 | expect_is(aa, "list") 15 | expect_named(aa) 16 | expect_null(aa$error) 17 | expect_is(aa$data, "list") 18 | expect_equal(aa$data$package, "worrms") 19 | expect_is(aa$data$summary, "list") 20 | expect_is(aa$data$summary$any, "logical") 21 | expect_is(aa$data$checks, "data.frame") 22 | expect_match(aa$data$date_updated, "[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}") 23 | 24 | vcr::use_cassette("cch_pkgs_all_pkgs", { 25 | cc <- cch_pkgs() 26 | }) 27 | 28 | expect_is(cc, "list") 29 | expect_named(cc) 30 | expect_is(cc$data, "data.frame") 31 | expect_is(cc$found, "integer") 32 | expect_is(cc$count, "integer") 33 | expect_is(cc$offset, "integer") 34 | expect_null(cc$error) 35 | expect_named(cc$data) 36 | }) 37 | 38 | # FIXME: async can't be mocked/vcr right now 39 | # vcr::use_cassette("cch_pkgs_many_pkgs", { 40 | # bb <- cch_pkgs(c("worrms", "taxize", "charlatan", "rgbif")) 41 | # }) 42 | # expect_is(bb, "list") 43 | # expect_named(bb, NULL) 44 | # expect_equal(length(bb), 4) 45 | # expect_null(bb[[2]]$error) 46 | # expect_is(bb[[2]]$data, "list") 47 | # expect_equal(bb[[2]]$data$package, "taxize") 48 | # expect_is(bb[[2]]$data$summary, "list") 49 | # expect_is(bb[[2]]$data$summary$any, "logical") 50 | # expect_is(bb[[2]]$data$checks, "data.frame") 51 | # expect_match(bb[[2]]$data$date_updated, "[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}") 52 | -------------------------------------------------------------------------------- /tests/testthat/test-cch_pkgs_history.R: -------------------------------------------------------------------------------- 1 | test_that("cch_pkgs_history fails well", { 2 | vcr::use_cassette("cch_pkgs_history_error", { 3 | expect_error(cch_pkgs_history("x", limit = "foo"), "limit is not an integer") 4 | expect_error(cch_pkgs_history("x", offset = "bar"), "offset is not an integer") 5 | expect_error(cch_pkgs_history(x = "aaaaaaaaaaa"), "no results found") 6 | }) 7 | }) 8 | 9 | test_that("cch_pkgs_history", { 10 | vcr::use_cassette("cch_pkgs_history_one_pkg", { 11 | aa <- cch_pkgs_history("worrms") 12 | }) 13 | 14 | expect_is(aa, "list") 15 | expect_named(aa) 16 | expect_null(aa$error) 17 | expect_is(aa$data, "list") 18 | expect_equal(aa$data$package, "worrms") 19 | expect_is(aa$data$history$summary, "data.frame") 20 | expect_is(aa$data$history$summary$any, "logical") 21 | expect_is(aa$data$history$checks, "list") 22 | expect_match(aa$data$history$date_updated, "[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}") 23 | }) 24 | 25 | test_that("cch_pkgs_history - many pkgs", { 26 | # FIXME: can't be cached - vcr can't handle async yet 27 | skip_on_ci() 28 | skip_on_cran() 29 | 30 | cc <- cch_pkgs_history(c("leaflet", "stringi")) 31 | expect_is(cc, "list") 32 | expect_named(cc, NULL) 33 | expect_null(cc$error) 34 | 35 | expect_is(cc[[1]]$data, "list") 36 | expect_equal(cc[[1]]$data$package, "leaflet") 37 | 38 | expect_is(cc[[2]]$data, "list") 39 | expect_equal(cc[[2]]$data$package, "stringi") 40 | }) 41 | -------------------------------------------------------------------------------- /tests/testthat/test-cch_pkgs_search.R: -------------------------------------------------------------------------------- 1 | test_that("cch_pkgs_search fails well", { 2 | vcr::use_cassette("cch_pkgs_search_error", { 3 | expect_error(cch_pkgs_search("foo", limit = "foo"), "limit is not an integer") 4 | expect_error(cch_pkgs_search("foo", offset = "bar"), "offset is not an integer") 5 | expect_error(cch_pkgs_search("aaaaaaaaaaa"), "no results found") 6 | }) 7 | }) 8 | 9 | test_that("cch_pkgs_search", { 10 | vcr::use_cassette("cch_pkgs_search", { 11 | aa <- cch_pkgs_search("memory") 12 | }) 13 | 14 | expect_is(aa, "list") 15 | expect_named(aa) 16 | expect_null(aa$error) 17 | expect_is(aa$data, "data.frame") 18 | expect_is(aa$data$package, "character") 19 | expect_is(aa$data$summary, "data.frame") 20 | expect_is(aa$data$summary$any, "logical") 21 | expect_is(aa$data$checks, "list") 22 | expect_match(aa$data$check_details$output[1], "memory") 23 | expect_match(aa$data$date_updated, "[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}") 24 | 25 | vcr::use_cassette("cch_pkgs_search_limit_by_package", { 26 | cc <- cch_pkgs_search("memory", package = "apsimr") 27 | }) 28 | 29 | expect_is(cc, "list") 30 | expect_named(cc) 31 | expect_is(cc$data, "data.frame") 32 | expect_equal(unique(cc$data$package), "apsimr") 33 | expect_equal(length(unique(cc$data$package)), 1) 34 | }) 35 | -------------------------------------------------------------------------------- /tests/testthat/test-cchn_pkg_rule_add.R: -------------------------------------------------------------------------------- 1 | email <- "sckott7@gmail.com" 2 | 3 | testthat::setup({ 4 | options(usethis.quiet=TRUE) # quiet usethis 5 | }) 6 | testthat::teardown({ 7 | options(usethis.quiet=FALSE) 8 | }) 9 | 10 | test_that("cchn_pkg_rule_add", { 11 | skip_on_ci() 12 | 13 | path <- fake_pkg("bubbles") 14 | on.exit(unlink(path, recursive = TRUE), add = TRUE) 15 | 16 | vcr::use_cassette("cchn_pkg_rule_add", { 17 | x <- cchn_pkg_rule_add(status = "note", platform = 3, 18 | quiet = TRUE, path = path) 19 | rules <- cchn_pkg_rule_list(path = path) 20 | }) 21 | 22 | expect_is(x, "list") 23 | expect_named(x, c("error","data")) 24 | expect_null(x$error) 25 | expect_is(x$data, "data.frame") 26 | expect_is(x$data$id, "integer") 27 | expect_is(x$data$already_existed, "logical") 28 | expect_is(x$data$rule, "character") 29 | 30 | dat <- rules$data 31 | fb <- dat[dat$package == "bubbles", ] 32 | expect_equal(sort(names(fb)), 33 | c("id", "package", "rule_platforms", "rule_regex", 34 | "rule_status", "rule_time")) 35 | expect_equal(fb$package, "bubbles") 36 | 37 | # cleanup 38 | vcr::use_cassette("cchn_pkg_rule_add_cleanup", { 39 | cchn_pkg_rule_delete(fb$id, path = path) 40 | }) 41 | }) 42 | -------------------------------------------------------------------------------- /tests/testthat/test-cchn_pkg_rule_get.R: -------------------------------------------------------------------------------- 1 | email <- "sckott7@gmail.com" 2 | 3 | testthat::setup({ 4 | options(usethis.quiet=TRUE) # quiet usethis 5 | }) 6 | testthat::teardown({ 7 | options(usethis.quiet=FALSE) 8 | }) 9 | 10 | test_that("cchn_pkg_rule_get fails well", { 11 | skip_on_ci() 12 | 13 | expect_error(cchn_pkg_rule_get(email = email), "missing") 14 | expect_error(cchn_pkg_rule_get("asdasdf", email = email), "class") 15 | }) 16 | 17 | test_that("cchn_pkg_rule_get", { 18 | skip_on_ci() 19 | 20 | # rule not found 21 | vcr::use_cassette("cchn_pkg_rule_get_not_found", { 22 | expect_error(cchn_pkg_rule_get(id = 578999, email = email), 23 | "not found") 24 | }) 25 | 26 | path <- fake_pkg("honeybadger") 27 | on.exit(unlink(path, recursive = TRUE), add = TRUE) 28 | 29 | # add a rule 30 | vcr::use_cassette("cchn_pkg_rule_get_add_rule", { 31 | cchn_rule_add(status = "warn", package = "honeybadger", time = 6, 32 | email = email, quiet = TRUE) 33 | }) 34 | 35 | # after a rule added 36 | vcr::use_cassette("cchn_pkg_rule_get_one_rule", { 37 | rules <- cchn_pkg_rule_list(path = path) 38 | rule <- cchn_pkg_rule_get(rules$data$id[1], path = path) 39 | }) 40 | expect_is(rule, "list") 41 | expect_named(rule, c("error", "data")) 42 | expect_is(rule$data, "list") 43 | expect_is(rule$data$id, "integer") 44 | expect_is(rule$data$package, "character") 45 | expect_is(rule$data$rule_status, "character") 46 | expect_is(rule$data$rule_time, "integer") 47 | expect_null(rule$data$rule_platforms, "character") 48 | expect_null(rule$data$rule_regex, "character") 49 | expect_equal(rule$data$package, "honeybadger") 50 | 51 | # cleanup 52 | vcr::use_cassette("cchn_pkg_rule_get_cleanup", { 53 | cchn_pkg_rule_delete(rule$data$id, path = path) 54 | }) 55 | }) 56 | -------------------------------------------------------------------------------- /tests/testthat/test-cchn_pkg_rule_list.R: -------------------------------------------------------------------------------- 1 | email <- "sckott7@gmail.com" 2 | 3 | testthat::setup({ 4 | options(usethis.quiet=TRUE) # quiet usethis 5 | }) 6 | testthat::teardown({ 7 | options(usethis.quiet=FALSE) 8 | }) 9 | 10 | test_that("cchn_pkg_rule_list fails well", { 11 | skip_on_ci() 12 | 13 | expect_error(cchn_pkg_rule_list()) 14 | expect_error(cchn_pkg_rule_list("asdasdf"), 15 | "`email` is not a valid email") 16 | expect_error(cchn_pkg_rule_list(path = "asdasdf"), "No such") 17 | }) 18 | 19 | test_that("cchn_pkg_rule_list", { 20 | skip_on_ci() 21 | 22 | path <- fake_pkg("rgbif") 23 | on.exit(unlink(path, recursive = TRUE), add = TRUE) 24 | 25 | # before any rules added 26 | vcr::use_cassette("cchn_pkg_rule_list_empty", { 27 | rules <- cchn_pkg_rule_list(path = path) 28 | }) 29 | expect_is(rules, "list") 30 | expect_is(rules$data, "list") 31 | expect_equal(length(rules$data), 0) 32 | 33 | # add a rule 34 | vcr::use_cassette("cchn_pkg_rule_list_add_rule", { 35 | cchn_pkg_rule_add(status = "note", quiet = TRUE, path = path) 36 | }) 37 | 38 | # after a rule added 39 | vcr::use_cassette("cchn_pkg_rule_list_one_rule", { 40 | rules <- cchn_pkg_rule_list(path = path) 41 | }) 42 | expect_is(rules, "list") 43 | expect_is(rules$data, "data.frame") 44 | expect_equal(NROW(rules$data), 1) 45 | 46 | # cleanup 47 | vcr::use_cassette("cchn_pkg_rule_list_cleanup", { 48 | cchn_pkg_rule_delete(rules$data$id[1], path = path) 49 | }) 50 | }) 51 | -------------------------------------------------------------------------------- /tests/testthat/test-cchn_rule_add.R: -------------------------------------------------------------------------------- 1 | email <- "sckott7@gmail.com" 2 | pkg <- "testing123" 3 | 4 | test_that("cchn_rule_add", { 5 | skip_on_ci() 6 | 7 | vcr::use_cassette("cchn_rule_add", { 8 | x <- cchn_rule_add(package = pkg, status = "warn", platform = 2, 9 | email = email, quiet = TRUE) 10 | rules <- cchn_rule_list(email = email) 11 | }) 12 | 13 | expect_is(x, "list") 14 | expect_named(x, c("error","data")) 15 | expect_null(x$error) 16 | expect_is(x$data, "data.frame") 17 | expect_is(x$data$id, "integer") 18 | expect_is(x$data$already_existed, "logical") 19 | expect_is(x$data$rule, "character") 20 | 21 | dat <- rules$data 22 | fb <- dat[dat$package == pkg, ] 23 | expect_equal(sort(names(fb)), 24 | c("id", "package", "rule_platforms", "rule_regex", 25 | "rule_status", "rule_time")) 26 | expect_equal(fb$package, pkg) 27 | 28 | # cleanup 29 | vcr::use_cassette("cchn_rule_add_cleanup", { 30 | cchn_rule_delete(fb$id, email = email) 31 | }) 32 | }) 33 | -------------------------------------------------------------------------------- /tests/testthat/test-cchn_rule_get.R: -------------------------------------------------------------------------------- 1 | email <- "sckott7@gmail.com" 2 | 3 | test_that("cchn_rule_get fails well", { 4 | skip_on_ci() 5 | 6 | # id is missing 7 | expect_error(cchn_rule_get(email = email), "missing") 8 | # id wrong class 9 | expect_error(cchn_rule_get("asdasdf", email = email), "class") 10 | }) 11 | 12 | test_that("cchn_rule_get", { 13 | skip_on_ci() 14 | 15 | # rule not found 16 | vcr::use_cassette("cchn_rule_get_not_found", { 17 | expect_error(cchn_rule_get(id = 578999, email = email), 18 | "not found") 19 | }) 20 | 21 | # fails as expected when cchn_rule_list is empty 22 | vcr::use_cassette("cchn_rule_get_empty_rule_list", { 23 | x <- cchn_rule_list(email = email) 24 | expect_error(cchn_rule_get(x$data$id, email = email), 25 | "id length can not be 0") 26 | }) 27 | 28 | # add a rule 29 | vcr::use_cassette("cchn_rule_get_add_rule", { 30 | cchn_rule_add(status = "warn", package = "honeybadger", time = 6, 31 | email = email, quiet = TRUE) 32 | }) 33 | 34 | # after a rule added 35 | vcr::use_cassette("cchn_rule_get_one_rule", { 36 | rules <- cchn_rule_list(email = email) 37 | rule <- cchn_rule_get(rules$data$id[1], email = email) 38 | }) 39 | expect_is(rule, "list") 40 | expect_named(rule, c("error", "data")) 41 | expect_is(rule$data, "list") 42 | expect_is(rule$data$id, "integer") 43 | expect_is(rule$data$package, "character") 44 | expect_is(rule$data$rule_status, "character") 45 | expect_is(rule$data$rule_time, "integer") 46 | expect_null(rule$data$rule_platforms, "character") 47 | expect_null(rule$data$rule_regex, "character") 48 | expect_equal(rule$data$package, "honeybadger") 49 | 50 | # cleanup 51 | vcr::use_cassette("cchn_rule_get_cleanup", { 52 | cchn_rule_delete(rule$data$id, email = email) 53 | }) 54 | }) 55 | -------------------------------------------------------------------------------- /tests/testthat/test-cchn_rule_list.R: -------------------------------------------------------------------------------- 1 | email <- "sckott7@gmail.com" 2 | 3 | test_that("cchn_rule_list fails well", { 4 | skip_on_ci() 5 | 6 | # email not validated 7 | expect_error(cchn_rule_list("asdasdf"), 8 | "`email` is not a valid email") 9 | # quiet must be a boolean 10 | expect_error(cchn_rule_list(quiet = 5)) 11 | }) 12 | 13 | test_that("cchn_rule_list", { 14 | skip_on_ci() 15 | 16 | # before any rules added 17 | vcr::use_cassette("cchn_rule_list_empty", { 18 | rules <- cchn_rule_list(email = email) 19 | }) 20 | expect_is(rules, "list") 21 | expect_is(rules$data, "list") 22 | expect_equal(length(rules$data), 0) 23 | 24 | # add a rule 25 | vcr::use_cassette("cchn_rule_list_add_rule", { 26 | cchn_rule_add(status = "note", package = "wombat", 27 | email = email, quiet = TRUE) 28 | }) 29 | 30 | # after a rule added 31 | vcr::use_cassette("cchn_rule_list_one_rule", { 32 | rules <- cchn_rule_list(email = email) 33 | }) 34 | expect_is(rules, "list") 35 | expect_is(rules$data, "data.frame") 36 | expect_equal(NROW(rules$data), 1) 37 | 38 | # cleanup 39 | vcr::use_cassette("cchn_rule_list_cleanup", { 40 | cchn_rule_delete(rules$data$id[1], email = email) 41 | }) 42 | }) 43 | -------------------------------------------------------------------------------- /tests/testthat/test-cchn_rules_add.R: -------------------------------------------------------------------------------- 1 | email <- "sckott7@gmail.com" 2 | pkg <- "testing456" 3 | 4 | test_that("cchn_rules_add", { 5 | skip_on_ci() 6 | 7 | rlz <- list( 8 | list(package = pkg, status = "warn"), 9 | list(package = pkg, status = "error", time = 4) 10 | ) 11 | 12 | vcr::use_cassette("cchn_rules_add", { 13 | x <- cchn_rules_add(rules = rlz, email = email, quiet = TRUE) 14 | rules <- cchn_rule_list(email = email) 15 | }) 16 | 17 | expect_is(x, "list") 18 | expect_named(x, c("error","data")) 19 | expect_null(x$error) 20 | expect_is(x$data, "data.frame") 21 | expect_is(x$data$id, "integer") 22 | expect_is(x$data$already_existed, "logical") 23 | expect_is(x$data$rule, "character") 24 | 25 | dat <- rules$data 26 | fb <- dat[dat$package == pkg, ] 27 | expect_equal(sort(names(fb)), 28 | c("id", "package", "rule_platforms", "rule_regex", 29 | "rule_status", "rule_time")) 30 | expect_equal(unique(fb$package), pkg) 31 | 32 | # cleanup 33 | vcr::use_cassette("cchn_rules_add_cleanup", { 34 | lapply(fb$id, cchn_rule_delete, email = email) 35 | }) 36 | }) 37 | 38 | test_that("cchn_rules_add fails well", { 39 | # missing rules param 40 | expect_error(cchn_rules_add(), "missing") 41 | # missing email param 42 | expect_error(cchn_rules_add(4), "missing") 43 | # rules wrong type 44 | expect_error(cchn_rules_add(4, email), "class list") 45 | # rules each element must be a list 46 | expect_error(cchn_rules_add(list(4, 5), email), "a list") 47 | # rules each element must be a named list, with names in acceptable set 48 | expect_error(cchn_rules_add(list(list(foo ="bar")), email), 49 | "one or more names") 50 | }) 51 | -------------------------------------------------------------------------------- /vignettes/cchecks.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | title: Client for the cranchecks.info API 3 | author: Scott Chamberlain 4 | date: "2020-05-19" 5 | output: rmarkdown::html_vignette 6 | vignette: > 7 | %\VignetteIndexEntry{Client for the cranchecks.info API} 8 | %\VignetteEngine{knitr::rmarkdown} 9 | %\VignetteEncoding{UTF-8} 10 | --- 11 | 12 | 13 | 14 | `cchecks` is a client for the API 15 | 16 | ## Install 17 | 18 | 19 | ```r 20 | remotes::install_github("ropensci/cchecks") 21 | ``` 22 | 23 | 24 | ```r 25 | library("cchecks") 26 | ``` 27 | 28 | ## heartbeat 29 | 30 | 31 | ```r 32 | cch_heartbeat() 33 | #> $routes 34 | #> [1] "/" "/docs" 35 | #> [3] "/heartbeat/?" "/pkgs" 36 | #> [5] "/pkgs/:name" "/maintainers" 37 | #> [7] "/maintainers/:email" "/badges/:type/:package" 38 | #> [9] "/badges/flavor/:flavor/:package" "/pkgs/:name/history" 39 | #> [11] "/history/:date" "/search" 40 | #> [13] "/notifications/rules" "/notifications/rules/:id" 41 | ``` 42 | 43 | ## packages 44 | 45 | all 46 | 47 | 48 | ```r 49 | cch_pkgs(limit = 1) 50 | #> $found 51 | #> [1] 16617 52 | #> 53 | #> $count 54 | #> [1] 1 55 | #> 56 | #> $offset 57 | #> [1] 0 58 | #> 59 | #> $error 60 | #> NULL 61 | #> 62 | #> $data 63 | #> package url 64 | #> 1 localIV https://cloud.r-project.org/web/checks/check_results_localIV.html 65 | #> date_updated summary.any summary.ok summary.note summary.warn 66 | #> 1 2020-05-20T00:04:00.609Z FALSE 12 0 0 67 | #> summary.error summary.fail 68 | #> 1 0 0 69 | #> checks 70 | #> 1 r-devel-linux-x86_64-debian-clang, r-devel-linux-x86_64-debian-gcc, r-devel-linux-x86_64-fedora-clang, r-devel-linux-x86_64-fedora-gcc, r-devel-windows-ix86+x86_64, r-patched-linux-x86_64, r-patched-solaris-x86, r-release-linux-x86_64, r-release-osx-x86_64, r-release-windows-ix86+x86_64, r-oldrel-osx-x86_64, r-oldrel-windows-ix86+x86_64, 0.3.0, 0.3.0, 0.3.0, 0.3.0, 0.3.0, 0.3.0, 0.3.0, 0.3.0, 0.3.0, 0.3.0, 0.3.0, 0.3.0, 2.62, 2.12, 0, 0, 16, 2.72, 0, 1.9, 0, 30, 0, 5, 42.55, 33.16, 0, 0, 53, 42.57, 0, 42.1, 0, 73, 0, 54, 45.17, 35.28, 54.87, 55, 69, 45.29, 82.6, 44, 0, 103, 0, 59, OK, OK, OK, OK, OK, OK, OK, OK, OK, OK, OK, OK, https://www.R-project.org/nosvn/R.check/r-devel-linux-x86_64-debian-clang/localIV-00check.html, https://www.R-project.org/nosvn/R.check/r-devel-linux-x86_64-debian-gcc/localIV-00check.html, https://www.R-project.org/nosvn/R.check/r-devel-linux-x86_64-fedora-clang/localIV-00check.html, https://www.R-project.org/nosvn/R.check/r-devel-linux-x86_64-fedora-gcc/localIV-00check.html, https://www.R-project.org/nosvn/R.check/r-devel-windows-ix86+x86_64/localIV-00check.html, https://www.R-project.org/nosvn/R.check/r-patched-linux-x86_64/localIV-00check.html, https://www.R-project.org/nosvn/R.check/r-patched-solaris-x86/localIV-00check.html, https://www.R-project.org/nosvn/R.check/r-release-linux-x86_64/localIV-00check.html, https://www.R-project.org/nosvn/R.check/r-release-osx-x86_64/localIV-00check.html, https://www.R-project.org/nosvn/R.check/r-release-windows-ix86+x86_64/localIV-00check.html, https://www.R-project.org/nosvn/R.check/r-oldrel-osx-x86_64/localIV-00check.html, https://www.R-project.org/nosvn/R.check/r-oldrel-windows-ix86+x86_64/localIV-00check.html 71 | #> check_details 72 | #> 1 NA 73 | ``` 74 | 75 | by name 76 | 77 | 78 | ```r 79 | x <- cch_pkgs(c("geojsonio", "leaflet", "MASS")) 80 | lapply(x, "[[", c("data", "summary")) 81 | #> [[1]] 82 | #> [[1]]$any 83 | #> [1] TRUE 84 | #> 85 | #> [[1]]$ok 86 | #> [1] 11 87 | #> 88 | #> [[1]]$note 89 | #> [1] 1 90 | #> 91 | #> [[1]]$warn 92 | #> [1] 0 93 | #> 94 | #> [[1]]$error 95 | #> [1] 0 96 | #> 97 | #> [[1]]$fail 98 | #> [1] 0 99 | #> 100 | #> 101 | #> [[2]] 102 | #> [[2]]$any 103 | #> [1] TRUE 104 | #> 105 | #> [[2]]$ok 106 | #> [1] 11 107 | #> 108 | #> [[2]]$note 109 | #> [1] 1 110 | #> 111 | #> [[2]]$warn 112 | #> [1] 0 113 | #> 114 | #> [[2]]$error 115 | #> [1] 0 116 | #> 117 | #> [[2]]$fail 118 | #> [1] 0 119 | #> 120 | #> 121 | #> [[3]] 122 | #> [[3]]$any 123 | #> [1] FALSE 124 | #> 125 | #> [[3]]$ok 126 | #> [1] 12 127 | #> 128 | #> [[3]]$note 129 | #> [1] 0 130 | #> 131 | #> [[3]]$warn 132 | #> [1] 0 133 | #> 134 | #> [[3]]$error 135 | #> [1] 0 136 | #> 137 | #> [[3]]$fail 138 | #> [1] 0 139 | ``` 140 | 141 | historical data 142 | 143 | 144 | ```r 145 | x <- cch_pkgs_history(x = "geojsonio") 146 | x$data$history 147 | #> # A tibble: 30 x 4 148 | #> date_updated summary$any $ok $note $warn $error $fail checks 149 | #> 150 | #> 1 2020-05-19T… TRUE 11 1 0 0 0 2 2020-05-18T… TRUE 11 1 0 0 0 3 2020-05-17T… TRUE 11 1 0 0 0 4 2020-05-16T… TRUE 10 1 1 0 0 5 2020-05-15T… TRUE 11 1 0 0 0 6 2020-05-14T… TRUE 11 1 0 0 0 7 2020-05-13T… TRUE 11 1 0 0 0 8 2020-05-12T… TRUE 11 1 0 0 0 9 2020-05-11T… TRUE 11 1 0 0 0 10 2020-05-10T… TRUE 11 1 0 0 0 # … with 20 more rows, and 6 more variables: check_details$version , 161 | #> # $check , $result , $output , $flavors , 162 | #> # $additional_issues 163 | ``` 164 | 165 | search historical data 166 | 167 | 168 | ```r 169 | x <- cch_pkgs_search(q = "memory") 170 | x$data 171 | #> # A tibble: 30 x 5 172 | #> package date_updated summary$any $ok $note $warn $error $fail checks 173 | #> 174 | #> 1 tidyft 2020-04-20T… TRUE 9 0 2 0 0 2 tidyft 2020-04-21T… TRUE 10 0 2 0 0 3 tidyft 2020-04-22T… TRUE 10 0 2 0 0 4 tidyft 2020-04-23T… TRUE 10 0 2 0 0 5 tidyft 2020-04-24T… TRUE 10 0 2 0 0 6 tidyft 2020-04-25T… TRUE 10 0 2 0 0 7 tidyft 2020-04-26T… TRUE 10 0 2 0 0 8 tidyft 2020-04-27T… TRUE 10 0 2 0 0 9 tidyft 2020-04-28T… TRUE 10 0 2 0 0 10 tidyft 2020-04-29T… TRUE 10 0 2 0 0 # … with 20 more rows, and 6 more variables: check_details$version , 185 | #> # $check , $result , $output , $flavors , 186 | #> # $additional_issues 187 | ``` 188 | 189 | ## maintainers 190 | 191 | all 192 | 193 | 194 | ```r 195 | cch_maintainers(limit = 1) 196 | #> $found 197 | #> [1] 9450 198 | #> 199 | #> $count 200 | #> [1] 1 201 | #> 202 | #> $offset 203 | #> [1] 0 204 | #> 205 | #> $error 206 | #> NULL 207 | #> 208 | #> $data 209 | #> email name 210 | #> 1 f.briatte_at_gmail.com François Briatte 211 | #> url 212 | #> 1 https://cloud.r-project.org/web/checks/check_results_f.briatte_at_gmail.com.html 213 | #> date_updated table 214 | #> 1 2020-05-20T00:02:21.528Z ggnetwork, TRUE, 7, 5, 0, 0 215 | #> packages 216 | #> 1 ggnetwork, https://cloud.r-project.org/web/checks/check_results_ggnetwork.html, NOTE, OK, 5, 7, NA 217 | ``` 218 | 219 | by name 220 | 221 | 222 | ```r 223 | cch_maintainers(c("maelle.salmon_at_yahoo.se", "13268259225_at_163.com")) 224 | #> [[1]] 225 | #> [[1]]$error 226 | #> NULL 227 | #> 228 | #> [[1]]$data 229 | #> [[1]]$data$email 230 | #> [1] "maelle.salmon_at_yahoo.se" 231 | #> 232 | #> [[1]]$data$name 233 | #> [1] "Maëlle Salmon" 234 | #> 235 | #> [[1]]$data$url 236 | #> [1] "https://cloud.r-project.org/web/checks/check_results_maelle.salmon_at_yahoo.se.html" 237 | #> 238 | #> [[1]]$data$date_updated 239 | #> [1] "2020-05-20T00:02:21.579Z" 240 | #> 241 | #> [[1]]$data$table 242 | #> package any ok note warn error 243 | #> 1 monkeylearn TRUE 7 5 0 0 244 | #> 2 opencage TRUE 6 6 0 0 245 | #> 3 riem FALSE 12 0 0 0 246 | #> 4 ropenaq FALSE 12 0 0 0 247 | #> 5 rtimicropem TRUE 7 5 0 0 248 | #> 249 | #> [[1]]$data$packages 250 | #> package 251 | #> 1 monkeylearn 252 | #> 2 opencage 253 | #> 3 riem 254 | #> 4 ropenaq 255 | #> 5 rtimicropem 256 | #> url 257 | #> 1 https://cloud.r-project.org/web/checks/check_results_monkeylearn.html 258 | #> 2 https://cloud.r-project.org/web/checks/check_results_opencage.html 259 | #> 3 https://cloud.r-project.org/web/checks/check_results_riem.html 260 | #> 4 https://cloud.r-project.org/web/checks/check_results_ropenaq.html 261 | #> 5 https://cloud.r-project.org/web/checks/check_results_rtimicropem.html 262 | #> check_result version 263 | #> 1 NOTE, OK, 5, 7 NA 264 | #> 2 NOTE, OK, 6, 6 NA 265 | #> 3 OK, 12 NA 266 | #> 4 OK, 12 NA 267 | #> 5 NOTE, OK, 5, 7 NA 268 | #> 269 | #> 270 | #> 271 | #> [[2]] 272 | #> [[2]]$error 273 | #> NULL 274 | #> 275 | #> [[2]]$data 276 | #> [[2]]$data$email 277 | #> [1] "13268259225_at_163.com" 278 | #> 279 | #> [[2]]$data$name 280 | #> [1] "Xiao-Ping You" 281 | #> 282 | #> [[2]]$data$url 283 | #> [1] "https://cloud.r-project.org/web/checks/check_results_13268259225_at_163.com.html" 284 | #> 285 | #> [[2]]$data$date_updated 286 | #> [1] "2020-05-20T00:02:22.034Z" 287 | #> 288 | #> [[2]]$data$table 289 | #> package any ok note warn error 290 | #> 1 XHWE TRUE 0 12 0 0 291 | #> 292 | #> [[2]]$data$packages 293 | #> package url 294 | #> 1 XHWE https://cloud.r-project.org/web/checks/check_results_XHWE.html 295 | #> check_result version 296 | #> 1 NULL NA 297 | ``` 298 | -------------------------------------------------------------------------------- /vignettes/cchecks.Rmd.og: -------------------------------------------------------------------------------- 1 | --- 2 | title: Client for the cranchecks.info API 3 | author: Scott Chamberlain 4 | date: "`r Sys.Date()`" 5 | output: rmarkdown::html_vignette 6 | vignette: > 7 | %\VignetteIndexEntry{Client for the cranchecks.info API} 8 | %\VignetteEngine{knitr::rmarkdown} 9 | %\VignetteEncoding{UTF-8} 10 | --- 11 | 12 | ```{r echo=FALSE} 13 | NOT_CRAN <- identical(tolower(Sys.getenv("NOT_CRAN")), "true") 14 | knitr::opts_chunk$set( 15 | comment = "#>", 16 | collapse = TRUE, 17 | warning = FALSE, 18 | message = FALSE, 19 | purl = NOT_CRAN, 20 | eval = NOT_CRAN 21 | ) 22 | ``` 23 | 24 | `cchecks` is a client for the API 25 | 26 | ## Install 27 | 28 | ```{r eval=FALSE} 29 | remotes::install_github("ropensci/cchecks") 30 | ``` 31 | 32 | ```{r} 33 | library("cchecks") 34 | ``` 35 | 36 | ## heartbeat 37 | 38 | ```{r} 39 | cch_heartbeat() 40 | ``` 41 | 42 | ## packages 43 | 44 | all 45 | 46 | ```{r} 47 | cch_pkgs(limit = 1) 48 | ``` 49 | 50 | by name 51 | 52 | ```{r} 53 | x <- cch_pkgs(c("geojsonio", "leaflet", "MASS")) 54 | lapply(x, "[[", c("data", "summary")) 55 | ``` 56 | 57 | historical data 58 | 59 | ```{r} 60 | x <- cch_pkgs_history(x = "geojsonio") 61 | x$data$history 62 | ``` 63 | 64 | search historical data 65 | 66 | ```{r} 67 | x <- cch_pkgs_search(q = "memory") 68 | x$data 69 | ``` 70 | 71 | ## maintainers 72 | 73 | all 74 | 75 | ```{r} 76 | cch_maintainers(limit = 1) 77 | ``` 78 | 79 | by name 80 | 81 | ```{r} 82 | cch_maintainers(c("maelle.salmon_at_yahoo.se", "13268259225_at_163.com")) 83 | ``` 84 | --------------------------------------------------------------------------------