diff --git a/.github/skills/create-issue/SKILL.md b/.github/skills/create-issue/SKILL.md index d5a19b8..8a5762d 100644 --- a/.github/skills/create-issue/SKILL.md +++ b/.github/skills/create-issue/SKILL.md @@ -13,14 +13,14 @@ If `gh` is not authenticated, stop and ask the user to authenticate before conti ## Looking up IDs -The hardcoded IDs below are correct for this repo as of 2026-05-11 21:33:53 UTC. If they ever change, or if you're working in a fork, re-run these queries to get fresh values: +The hardcoded IDs below are correct for this repo as of 2026-05-15 13:57:23 UTC. If they ever change, or if you're working in a fork, re-run these queries to get fresh values: ```bash # Repository node ID -gh api graphql -f query='{ repository(owner: "jonthegeek", name: "beekeeper") { id } }' +gh api graphql -f query='{ repository(owner: "api2r", name: "beekeeper") { id } }' # Available issue type IDs -gh api graphql -f query='{ repository(owner: "jonthegeek", name: "beekeeper") { issueTypes(first: 20) { nodes { id name description } } } }' +gh api graphql -f query='{ repository(owner: "api2r", name: "beekeeper") { issueTypes(first: 20) { nodes { id name description } } } }' ``` ## Issue type @@ -29,6 +29,11 @@ Choose the type that best fits the issue: | Type | ID | Use for | |---|---|---| +| Task | `IT_kwDOCPuMJs4BPtRZ` | A specific piece of work | +| Bug | `IT_kwDOCPuMJs4BPtRc` | An unexpected problem or behavior | +| Feature | `IT_kwDOCPuMJs4BPtRe` | A request, idea, or new functionality | +| Documentation | `IT_kwDOCPuMJs4B5OL_` | Explanations of how or why to do things | +| Infrastructure | `IT_kwDOCPuMJs4B5OMn` | Infrastructure of a project, like GitHub Actions | ## Issue title diff --git a/.github/skills/r-code/SKILL.md b/.github/skills/r-code/SKILL.md index 70350d8..707e335 100644 --- a/.github/skills/r-code/SKILL.md +++ b/.github/skills/r-code/SKILL.md @@ -6,7 +6,7 @@ description: Guide for writing R code. Use when writing new functions, designing # R code -This skill covers how to design and write R functions — including naming conventions, signatures, API conventions, input validation, error handling, and common pitfalls. For documenting functions, use the `document` skill. For tests, use the `tdd-workflow` skill. +This skill covers how to design and write R functions — including naming conventions, signatures, API conventions, input validation, condition handling, and common pitfalls. For documenting functions, use the `document` skill. For tests, use the `tdd-workflow` skill. ## Naming conventions @@ -184,9 +184,9 @@ Keep a function internal when: Internal helpers use a dot prefix (e.g. `.parse_response()`). -## Error handling +## Condition handling -Use `.pkg_abort()` (defined in `R/aaa-conditions.R`) rather than calling `cli::cli_abort()` directly. This wraps `stbl::pkg_abort()` and ensures consistent error class formatting: +Use `.pkg_abort()`, `.pkg_warn()`, and `.pkg_inform()` (defined in `R/aaa-conditions.R`) rather than calling `cli::cli_abort()`, `cli::cli_warn()`, or `cli::cli_inform()` directly. These wrap `stbl` condition helpers and ensure consistent class formatting: ```r .pkg_abort( diff --git a/.github/skills/tdd-workflow/SKILL.md b/.github/skills/tdd-workflow/SKILL.md index a480565..2fd5a3c 100644 --- a/.github/skills/tdd-workflow/SKILL.md +++ b/.github/skills/tdd-workflow/SKILL.md @@ -133,8 +133,31 @@ test_that("process_data() errors on empty input (#42)", { }) ``` -Pass `transform = stbl::.transform_path(path)` to scrub volatile values (e.g. temp -paths) from the snapshot before comparison. +**Warnings thrown by this package** (via `.pkg_warn()`) should be tested with +`stbl::expect_pkg_warning_snapshot()`: + +```r +test_that("process_data() warns on dropped rows (#42)", { + stbl::expect_pkg_warning_snapshot( + process_data(data.frame(value = c(1, NA))), + "beekeeper", + "dropped_rows" + ) +}) +``` + +**Messages thrown by this package** (via `.pkg_inform()`) should be tested with +`stbl::expect_pkg_message_snapshot()`: + +```r +test_that("process_data() informs on defaults used (#42)", { + stbl::expect_pkg_message_snapshot( + process_data(data.frame(value = 1)), + "beekeeper", + "used_defaults" + ) +}) +``` **Errors thrown by `stbl`** (via `stbl::to_*()` / `stbl::stabilize_*()`) should be tested with `stbl::expect_pkg_error_classes()`. Since the message diff --git a/DESCRIPTION b/DESCRIPTION index bd5d47f..025c358 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -28,7 +28,7 @@ Imports: rprojroot, S7, snakecase, - stbl (>= 0.3.0), + stbl (>= 0.3.0.9000), stringr, testthat, tibble, @@ -49,7 +49,8 @@ VignetteBuilder: knitr Remotes: api2r/nectar, - api2r/rapid + api2r/rapid, + wranglezone/stbl Config/roxygen2/version: 8.0.0 Config/testthat/edition: 3 Encoding: UTF-8 diff --git a/R/aaa-conditions.R b/R/aaa-conditions.R index 1e416a3..4ce7af5 100644 --- a/R/aaa-conditions.R +++ b/R/aaa-conditions.R @@ -1,4 +1,4 @@ -#' Raise a package-scoped error +#' Signal a package-scoped error #' #' @inheritParams .shared-params #' @inheritParams stbl::pkg_abort @@ -7,6 +7,7 @@ .pkg_abort <- function( message, subclass, + parent = NULL, call = rlang::caller_env(), message_env = rlang::caller_env(), ... @@ -17,6 +18,57 @@ subclass, call = call, message_env = message_env, + parent = parent, + ... + ) +} + +#' Signal a package-scoped warning +#' +#' @inheritParams .shared-params +#' @inheritParams stbl::pkg_warn +#' @returns `NULL`, invisibly (called for warning side effect). +#' @keywords internal +.pkg_warn <- function( + message, + subclass, + parent = NULL, + call = rlang::caller_env(), + message_env = rlang::caller_env(), + ... +) { + stbl::pkg_warn( + "beekeeper", + message, + subclass, + call = call, + message_env = message_env, + parent = parent, + ... + ) +} + +#' Signal a package-scoped message +#' +#' @inheritParams .shared-params +#' @inheritParams stbl::pkg_inform +#' @returns `NULL`, invisibly (called for message side effect). +#' @keywords internal +.pkg_inform <- function( + message, + subclass, + parent = NULL, + call = rlang::caller_env(), + message_env = rlang::caller_env(), + ... +) { + stbl::pkg_inform( + "beekeeper", + message, + subclass, + call = call, + message_env = message_env, + parent = parent, ... ) } diff --git a/man/dot-pkg_abort.Rd b/man/dot-pkg_abort.Rd index a9b46ce..47c00d4 100644 --- a/man/dot-pkg_abort.Rd +++ b/man/dot-pkg_abort.Rd @@ -2,11 +2,12 @@ % Please edit documentation in R/aaa-conditions.R \name{.pkg_abort} \alias{.pkg_abort} -\title{Raise a package-scoped error} +\title{Signal a package-scoped error} \usage{ .pkg_abort( message, subclass, + parent = NULL, call = rlang::caller_env(), message_env = rlang::caller_env(), ... @@ -19,6 +20,9 @@ formatted with \code{\link[cli:cli_bullets]{cli::cli_bullets()}}.} \item{subclass}{(\code{character}) Class(es) to assign to the error. Will be prefixed by "\{package\}-error-".} +\item{parent}{A parent condition, as you might create during a +\code{\link[rlang:try_fetch]{rlang::try_fetch()}}. See \code{\link[rlang:abort]{rlang::abort()}} for additional information.} + \item{call}{(\code{environment}) The caller environment for error messages.} \item{message_env}{(\code{environment}) The execution environment to use to @@ -31,6 +35,6 @@ evaluate variables in error messages.} Does not return. } \description{ -Raise a package-scoped error +Signal a package-scoped error } \keyword{internal} diff --git a/man/dot-pkg_inform.Rd b/man/dot-pkg_inform.Rd new file mode 100644 index 0000000..03836d8 --- /dev/null +++ b/man/dot-pkg_inform.Rd @@ -0,0 +1,40 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/aaa-conditions.R +\name{.pkg_inform} +\alias{.pkg_inform} +\title{Signal a package-scoped message} +\usage{ +.pkg_inform( + message, + subclass, + parent = NULL, + call = rlang::caller_env(), + message_env = rlang::caller_env(), + ... +) +} +\arguments{ +\item{message}{(\code{character}) The message for the new message condition. +Messages will be formatted with \code{\link[cli:cli_bullets]{cli::cli_bullets()}}.} + +\item{subclass}{(\code{character}) Class(es) to assign to the message. Will be +prefixed by "\{package\}-message-".} + +\item{parent}{A parent condition, as you might create during a +\code{\link[rlang:try_fetch]{rlang::try_fetch()}}. See \code{\link[rlang:abort]{rlang::abort()}} for additional information.} + +\item{call}{(\code{environment}) The caller environment for error messages.} + +\item{message_env}{(\code{environment}) The execution environment to use to +evaluate variables in error messages.} + +\item{...}{Additional parameters passed to \code{\link[cli:cli_abort]{cli::cli_inform()}} and on to +\code{\link[rlang:abort]{rlang::inform()}}.} +} +\value{ +\code{NULL}, invisibly (called for message side effect). +} +\description{ +Signal a package-scoped message +} +\keyword{internal} diff --git a/man/dot-pkg_warn.Rd b/man/dot-pkg_warn.Rd new file mode 100644 index 0000000..3e7a38d --- /dev/null +++ b/man/dot-pkg_warn.Rd @@ -0,0 +1,40 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/aaa-conditions.R +\name{.pkg_warn} +\alias{.pkg_warn} +\title{Signal a package-scoped warning} +\usage{ +.pkg_warn( + message, + subclass, + parent = NULL, + call = rlang::caller_env(), + message_env = rlang::caller_env(), + ... +) +} +\arguments{ +\item{message}{(\code{character}) The message for the new warning. Messages will +be formatted with \code{\link[cli:cli_bullets]{cli::cli_bullets()}}.} + +\item{subclass}{(\code{character}) Class(es) to assign to the warning. Will be +prefixed by "\{package\}-warning-".} + +\item{parent}{A parent condition, as you might create during a +\code{\link[rlang:try_fetch]{rlang::try_fetch()}}. See \code{\link[rlang:abort]{rlang::abort()}} for additional information.} + +\item{call}{(\code{environment}) The caller environment for error messages.} + +\item{message_env}{(\code{environment}) The execution environment to use to +evaluate variables in error messages.} + +\item{...}{Additional parameters passed to \code{\link[cli:cli_abort]{cli::cli_warn()}} and on to +\code{\link[rlang:abort]{rlang::warn()}}.} +} +\value{ +\code{NULL}, invisibly (called for warning side effect). +} +\description{ +Signal a package-scoped warning +} +\keyword{internal}