Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion DESCRIPTION
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
Type: Package
Package: audit.base
Title: Base package for Posit Checks
Version: 0.6.23
Version: 0.6.24
Authors@R:
person("Jumping", "Rivers", , "info@jumpingrivers.com", role = c("aut", "cre"))
Description: Base package for sharing classes between posit audit
Expand Down
3 changes: 3 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
# audit.base 0.6.24 _2026-02-01_
- fix: Adding end of life python versions - fixes #28

# audit.base 0.6.23 _2026-01-30_
- chore: Update quarto, requirements.txt and software versions

Expand Down
95 changes: 77 additions & 18 deletions R/software-versions.R
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
#' Augments installed software columns
#' @param installed A tibble with columns software and installed_version
#' @param remote Use remote server for obtain versions
#' @param verbose Default TRUE.
#' @export
augment_installed = function(installed, verbose = TRUE) {
augment_installed = function(installed, remote = FALSE, verbose = TRUE) {
installed$installed_major = get_major(installed$installed_version)
installed$installed_patch = get_patch(installed$installed_version)
installed = in_db(installed)
installed = add_upgrade_column(installed)
installed = in_db(installed, remote = remote)
installed = add_upgrade_column(installed, remote = remote)
installed$major = package_version(installed$major)
installed = dplyr::arrange(
installed,
Expand All @@ -22,6 +23,11 @@ augment_installed = function(installed, verbose = TRUE) {
#' @rdname augment_installed
#' @export
print_colour_versions = function(installed) {
# Selected installed and max version
installed = installed %>%
dplyr::group_by(.data$software) %>%
dplyr::filter(!is.na(.data$installed_version) | .data$major == max(.data$major))

for (i in seq_len(nrow(installed))) {
row = installed[i, ]
print_colour_version(row)
Expand All @@ -30,6 +36,9 @@ print_colour_versions = function(installed) {
}

print_colour_version = function(row) {
if (is.na(row$installed_version) && isFALSE(row$within_eol)) {
return(NULL)
}
major = if ("major" %in% colnames(row)) paste0(" v", row$major) else ""
software_name = glue::glue("{stringr::str_to_title(row$software)}{major}") # nolint
latest_version = glue::glue("v{row$version}") # nolint
Expand All @@ -40,14 +49,19 @@ print_colour_version = function(row) {
return(invisible(NULL))
}

if (isTRUE(row$upgrade)) {
if (isFALSE(row$within_eol)) {
cli::cli_alert_danger(
"{software_name}: v{row$installed_version} installed, \\
but EOL has past and should be removed."
)
} else if (isTRUE(row$upgrade)) {
cli::cli_alert_danger(
"{software_name}: v{row$installed_version} installed, \\
but {latest_version} available"
)
} else {
cli::cli_alert_success(
"{software_name}: Latest version installed v{row$installed_version}"
"{software_name}: Latest version installed"
)
}
invisible(NULL)
Expand All @@ -61,9 +75,9 @@ get_patch = function(v) {
}

# Checks if versions are in the DB
in_db = function(installed) {
in_db = function(installed, remote = FALSE) {
# latest/earliest versions stored in DB
software_range = get_latest_versions() %>%
software_range = get_latest_versions(remote = remote) %>%
dplyr::group_by(.data$software) %>%
dplyr::summarise(latest = max(.data$major), earliest = min(.data$major))

Expand All @@ -77,8 +91,8 @@ in_db = function(installed) {
dplyr::select(-"latest", -"earliest")
}

add_upgrade_column = function(installed) {
versions = versions_to_display(installed)
add_upgrade_column = function(installed, remote = FALSE) {
versions = versions_to_display(installed, remote = remote)
versions = versions %>%
dplyr::mutate(
upgrade = .data$patch > .data$installed_patch | .data$to_old
Expand All @@ -94,10 +108,10 @@ add_upgrade_column = function(installed) {
dplyr::select(versions, -"to_old", -"to_new")
}

versions_to_display = function(installed) {
latest = get_latest_versions()
versions_to_display = function(installed, remote = FALSE) {
latest_versions = get_latest_versions(remote = remote)

min_installed = latest %>%
min_installed = latest_versions %>%
dplyr::full_join(
installed,
by = c(
Expand All @@ -108,23 +122,38 @@ versions_to_display = function(installed) {
dplyr::group_by(.data$software, .drop = FALSE) %>%
dplyr::filter(!is.na(.data$installed_version)) %>%
dplyr::summarise(
installed_version_num = max(.data$version_num, 3, na.rm = TRUE)
installed_version_num = ifelse(
length(.data$version_num) == 0L | all(is.na(.data$version)),
3,
min(.data$version_num, na.rm = TRUE)
)
)

l = get_latest_versions() %>%
installed_with_full = latest_versions %>%
dplyr::full_join(
installed,
by = c(
"software" = "software",
"major" = "installed_major"
)
) %>%
)

all = installed_with_full %>%
dplyr::full_join(min_installed, by = c("software" = "software")) %>%
dplyr::group_by(.data$software) %>%
dplyr::filter(
.data$version_num <= .data$installed_version_num |
.data$version_num >= .data$installed_version_num |
is.na(.data$version_num)
)
) %>%
dplyr::arrange(.data$software, .data$version)

# Old versions don't appear - so just tidy up some NAs
l = dplyr::mutate(
all,
within_eol = ifelse(is.na(.data$within_eol), FALSE, .data$within_eol),
version = ifelse(is.na(.data$version), .data$installed_version, .data$version)
)

dplyr::select(l, -"version_num", -"installed_version_num")
}

Expand Down Expand Up @@ -152,7 +181,37 @@ get_latest_versions = function(remote = TRUE) {
versions = versions %>%
dplyr::group_by(.data$software) %>%
dplyr::mutate(
version_num = length(.data$major) - seq_along(.data$major) + 1L
version_num = length(.data$major) - seq_along(.data$major) + 1L,
within_eol = FALSE
)
versions %>%
add_python_eol() %>%
add_quarto_eol() %>%
add_r_eol()
}

add_python_eol = function(versions) {
eol_fname = system.file(
"extdata",
"versions",
"eol.csv",
package = "audit.base",
mustWork = TRUE
)
eol = readr::read_csv(eol_fname, col_types = "cD", skip = 1)
eol = eol[eol$end_of_life > Sys.Date(), ]
versions[versions$software == "python", ]$within_eol = FALSE
versions[versions$software == "python" & versions$major %in% eol$version, ]$within_eol = TRUE
versions
}

add_quarto_eol = function(versions) {
versions[versions$software == "quarto", ]$within_eol = TRUE
versions
}
add_r_eol = function(versions) {
# Versions of R 3.0 past EOL
versions[versions$software == "r", ]$within_eol = FALSE
versions[versions$software == "r" & startsWith(versions$major, "4"), ]$within_eol = TRUE
versions
}
12 changes: 12 additions & 0 deletions inst/extdata/versions/eol.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# https://devguide.python.org/versions/
version,end_of_life
"3.19","2035-10-01"
"3.18","2034-10-01"
"3.17","2033-10-01"
"3.16","2032-10-01"
"3.15","2031-10-01"
"3.14","2030-10-01"
"3.13","2029-10-01"
"3.12","2028-10-01"
"3.11","2027-10-01"
"3.10","2026-10-01"
4 changes: 3 additions & 1 deletion man/augment_installed.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

91 changes: 58 additions & 33 deletions tests/testthat/test-software-versions.R
Original file line number Diff line number Diff line change
@@ -1,52 +1,77 @@
test_that("Testing software versions", {
versions = get_latest_versions()
v_colnames = c("software", "version", "major", "patch", "version_num")
versions = get_latest_versions(remote = FALSE)
v_colnames = c("software", "version", "major", "patch", "version_num", "within_eol")
expect_equal(colnames(versions), v_colnames)
expect_gte(nrow(versions), 16)
})

installed = tibble::tibble(
software = c("r", "r", "python"),
installed_version = c("3.4.3", "3.5.3", "3.7.1")
)
augmented = augment_installed(installed)
test_that("Testing augment_installed (empty)", {
installed = tibble::tibble(software = character(0), installed_version = character(0))
augmented_empty = augment_installed(installed, remote = FALSE, verbose = FALSE)
expect_equal(
colnames(augmented),
colnames(augmented_empty),
c(
v_colnames[1:4],
"software",
"version",
"major",
"patch",
"within_eol",
paste0("installed_", c("version", "patch")),
"upgrade"
)
)
expect_equal(sum(!augmented$upgrade), 1)

# Check specific packages
augmented = augmented[!is.na(augmented$installed_version), ]
expect_equal(augmented$installed_patch, c(1, 3, 3))

# Test really old versions: Upgrade old version
installed = tibble::tibble(software = "r", installed_version = "1.5.3")
augmented = augment_installed(installed)
expect_equal(sum(augmented$upgrade), 10)

# Test version not in DB - don't upgrade
installed = tibble::tibble(software = "r", installed_version = "99.4.3")
augmented = augment_installed(installed)
expect_equal(sum(augmented$upgrade), 9)
})

test_that("Testing software versions quarto output", {
test_that("Testing augment_installed (old)", {
augmented_empty =
augment_installed(
tibble::tibble(
software = character(0),
installed_version = character(0)
),
remote = FALSE,
verbose = FALSE
)

# All really old versions
installed = tibble::tibble(
software = c("r", "r", "python"),
installed_version = c("3.4.3", "3.5.3", "3.7.1")
software = c("r", "python"),
installed_version = c("2.4.1", "3.2.1")
)
augmented = augment_installed(installed, remote = FALSE, verbose = FALSE)
expect_equal(nrow(augmented) - nrow(augmented_empty), 2)
expect_equal(sum(!augmented$upgrade), 0)

installed_augmented_versions = dplyr::left_join(
installed,
augmented,
by = dplyr::join_by(software, installed_version)
)
augmented = suppressMessages(augment_installed(installed))
out = list(versions = augmented)
q = get_quarto_software_versions(out)
expect_equal(
colnames(q),
c("software", "version", "installed_version", "upgrade")
nrow(installed_augmented_versions),
2
)
expect_true(all(is.logical(q$upgrade)))

expect_equal(sum(installed_augmented_versions$within_eol), 0)
expect_equal(sum(installed_augmented_versions$upgrade), 2)
})

test_that("Testing augment_installed (new)", {
# Test really old versions: Upgrade old version
installed = tibble::tibble(software = "r", installed_version = "4.4.3")
augmented = augment_installed(installed, remote = FALSE, verbose = FALSE)
augmented = augmented[augmented$version == "4.4.3", ]
expect_equal(nrow(augmented), 1)
expect_false(augmented$upgrade)
})

test_that("Testing augment_installed (future))", {
# Test version not in DB - don't upgrade
installed = tibble::tibble(software = "r", installed_version = "99.4.3")
augmented = augment_installed(installed, remote = FALSE, verbose = FALSE)
augmented = augmented[augmented$version == "99.4.3", ]
expect_equal(nrow(augmented), 1)
expect_false(augmented$upgrade)
})

test_that("Ensure that software versions are up to date", {
Expand Down