From 416c19c8b8e2d3bc84776462e36e796698188a88 Mon Sep 17 00:00:00 2001 From: Toby Dylan Hocking Date: Thu, 29 Aug 2024 10:52:56 -0400 Subject: [PATCH 1/5] expect title in README fails --- R/data.R | 2 +- R/stat-unique.r | 3 --- R/z_pages.R | 2 +- man/stat_unique.Rd | 5 ----- man/txhousing.Rd | 2 +- tests/testthat/test-compiler-ghpages.R | 13 ++++++++++--- 6 files changed, 13 insertions(+), 14 deletions(-) diff --git a/R/data.R b/R/data.R index 2f442f0d9..3c28c1795 100644 --- a/R/data.R +++ b/R/data.R @@ -173,7 +173,7 @@ #' Housing sales in TX. #' #' Information about the housing market in Texas provided by the TAMU -#' real estate center, \url{https://www.recenter.tamu.edu/}. +#' real estate center. #' #' @format A data frame with 8602 observations and 9 variables: #' \describe{ diff --git a/R/stat-unique.r b/R/stat-unique.r index 22c4b13ce..aae622a88 100644 --- a/R/stat-unique.r +++ b/R/stat-unique.r @@ -1,8 +1,5 @@ #' Remove duplicates. #' -#' @section Aesthetics: -#' \Sexpr[results=rd,stage=build]{animint2:::rd_aesthetics("stat", "unique")} -#' #' @export #' @inheritParams layer #' @inheritParams geom_point diff --git a/R/z_pages.R b/R/z_pages.R index 9945dace6..08987f146 100644 --- a/R/z_pages.R +++ b/R/z_pages.R @@ -92,7 +92,7 @@ animint2pages <- function(plot.list, github_repo, commit_message = "Commit from manage_gh_pages(repo, to_post, local_clone, commit_message) message(sprintf( "Visualization will be available at %s\nDeployment via GitHub Pages may take a few minutes...", viz_url)) - viz_owner_repo + list(owner_repo=viz_owner_repo, local_clone=local_clone, viz_url=viz_url, gh_pages_url=sprintf("https://github.com/%s/tree/gh-pages", viz_owner_repo)) } initial_commit <- function(local_clone, repo, viz_url) { diff --git a/man/stat_unique.Rd b/man/stat_unique.Rd index 7c65eb175..bd4ff0e80 100644 --- a/man/stat_unique.Rd +++ b/man/stat_unique.Rd @@ -60,11 +60,6 @@ the default plot specification, e.g. \code{\link{borders}}.} \description{ Remove duplicates. } -\section{Aesthetics}{ - -\Sexpr[results=rd,stage=build]{animint2:::rd_aesthetics("stat", "unique")} -} - \examples{ ggplot(mtcars, aes(vs, am)) + geom_point(alpha = 0.1) ggplot(mtcars, aes(vs, am)) + geom_point(alpha = 0.1, stat="unique") diff --git a/man/txhousing.Rd b/man/txhousing.Rd index ffbdb1e55..8118f1b33 100644 --- a/man/txhousing.Rd +++ b/man/txhousing.Rd @@ -22,6 +22,6 @@ txhousing } \description{ Information about the housing market in Texas provided by the TAMU -real estate center, \url{https://www.recenter.tamu.edu/}. +real estate center. } \keyword{datasets} diff --git a/tests/testthat/test-compiler-ghpages.R b/tests/testthat/test-compiler-ghpages.R index abefaa433..741497e2b 100644 --- a/tests/testthat/test-compiler-ghpages.R +++ b/tests/testthat/test-compiler-ghpages.R @@ -1,5 +1,6 @@ acontext("GitHub Pages") +library(animint2) viz <- animint( title="one to ten", source="https://github.com/animint/animint2/tree/master/tests/testthat/test-compiler-ghpages.R", @@ -22,9 +23,15 @@ test_that("error for viz with no source", { }, "plot.list does not contain option named source, which is required by animint2pages") }) -test_that("animint2pages() returns owner/repo string", { - viz_owner_repo <- animint2pages(viz, github_repo = "animint2pages_test_repo") - expect_is(viz_owner_repo, "character") +test_that("animint2pages() returns list of meta-data", { + result_list <- animint2pages(viz, github_repo = "animint2pages_test_repo") + expect_match(result_list$owner_repo, "animint2pages_test_repo") + expect_match(result_list$viz_url, "github.io/animint2pages_test_repo") + expect_match(result_list$gh_pages_url, "animint2pages_test_repo/tree/gh-pages") + README.md <- file.path(result_list$local_clone, "README.md") + README.lines <- readLines(README.md) + expected.line <- paste("##", viz$title) + expect_identical(README.lines[1], expected.line) }) test_that("animint2pages raises an error if no GitHub token is present", { From 132b723f782b3ab3144bfdb8e7bc05fadce53f41 Mon Sep 17 00:00:00 2001 From: Toby Dylan Hocking Date: Thu, 29 Aug 2024 12:35:17 -0400 Subject: [PATCH 2/5] animint2pages test uses gh DELETE POST in animint-test/animint2pages_test_repo --- DESCRIPTION | 2 +- NEWS.md | 5 +++++ R/z_pages.R | 17 ++++++++++------ man/animint2pages.Rd | 3 +++ tests/testthat/test-compiler-ghpages.R | 28 +++++++++++++++++++++++++- 5 files changed, 47 insertions(+), 8 deletions(-) diff --git a/DESCRIPTION b/DESCRIPTION index c5b97e9b2..2bcb621a6 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,6 +1,6 @@ Package: animint2 Title: Animated Interactive Grammar of Graphics -Version: 2024.8.27 +Version: 2024.8.29 URL: https://animint.github.io/animint2/ BugReports: https://github.com/animint/animint2/issues Authors@R: c( diff --git a/NEWS.md b/NEWS.md index bf56799df..86347c210 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,3 +1,8 @@ +# Changes in version 2024.8.29 (PR#147) + +- animint2pages initial commit README.md uses viz title. +- animint2pages gains owner argument, with default taken from `gh::gh_whoami` (same as before, always returns user, even when token has permissions on an org); this allows user to specify an org where the user/token has write permissions. This is used in a new test-compiler-ghpages.R, which now assumes `PAT_GITHUB` has Administration and Contents permissions for all repos in `animint-test` org, so our test code can delete the `animint2pages_test_repo`, create a new one, and then use animint2pages twice, to test the results of creation/update. + # Changes in version 2024.8.27 (PR#144) - Remove selenium, combine renderer tests into single CI job. diff --git a/R/z_pages.R b/R/z_pages.R index 08987f146..a070c3dcd 100644 --- a/R/z_pages.R +++ b/R/z_pages.R @@ -8,6 +8,7 @@ #' @param plot.list A named list of ggplots and option lists. #' @param github_repo The name of the GitHub repository to which the #' files will be pushed. +#' @param owner The user/org under which the repo will be created, default comes from \code{gh::gh_whoami}. #' @param commit_message A string specifying the commit message for #' the pushed files. #' @param private A logical flag indicating whether the GitHub @@ -35,7 +36,7 @@ #' } #' #' @export -animint2pages <- function(plot.list, github_repo, commit_message = "Commit from animint2pages", private = FALSE, required_opts = c("title","source"), ...) { +animint2pages <- function(plot.list, github_repo, owner=NULL, commit_message = "Commit from animint2pages", private = FALSE, required_opts = c("title","source"), ...) { for(opt in required_opts){ if(!opt %in% names(plot.list)){ stop(sprintf("plot.list does not contain option named %s, which is required by animint2pages", opt)) @@ -61,8 +62,10 @@ animint2pages <- function(plot.list, github_repo, commit_message = "Commit from stop("The github_repo argument should not contain '/'.") } # Check for existing repository - whoami <- suppressMessages(gh::gh_whoami()) - owner <- whoami[["login"]] + if(is.null(owner)){ + whoami <- suppressMessages(gh::gh_whoami()) + owner <- whoami[["login"]] + } viz_owner_repo <- paste0(owner, "/", github_repo) local_clone <- tempfile() if (!check_no_github_repo(owner, github_repo)) { @@ -86,7 +89,9 @@ animint2pages <- function(plot.list, github_repo, commit_message = "Commit from silent = TRUE ) if (!has_commits) { - initial_commit(local_clone, repo, viz_url) + title <- plot.list[["title"]] + if(!is.character(title))title <- "New animint visualization" + initial_commit(local_clone, repo, viz_url, title) } # Handle gh-pages branch manage_gh_pages(repo, to_post, local_clone, commit_message) @@ -95,9 +100,9 @@ animint2pages <- function(plot.list, github_repo, commit_message = "Commit from list(owner_repo=viz_owner_repo, local_clone=local_clone, viz_url=viz_url, gh_pages_url=sprintf("https://github.com/%s/tree/gh-pages", viz_owner_repo)) } -initial_commit <- function(local_clone, repo, viz_url) { +initial_commit <- function(local_clone, repo, viz_url, title) { readme_file_path <- file.path(local_clone, "README.md") - header <- "## New animint visualization\n" + header <- sprintf("## %s\n", title) url_hyperlink <- sprintf("[%s](%s)\n", viz_url, viz_url) full_content <- paste0(header, url_hyperlink) writeLines(full_content, readme_file_path) diff --git a/man/animint2pages.Rd b/man/animint2pages.Rd index 0c3b00930..f9f04b21e 100644 --- a/man/animint2pages.Rd +++ b/man/animint2pages.Rd @@ -7,6 +7,7 @@ animint2pages( plot.list, github_repo, + owner = NULL, commit_message = "Commit from animint2pages", private = FALSE, required_opts = c("title", "source"), @@ -19,6 +20,8 @@ animint2pages( \item{github_repo}{The name of the GitHub repository to which the files will be pushed.} +\item{owner}{The user/org under which the repo will be created, default comes from \code{gh::gh_whoami}.} + \item{commit_message}{A string specifying the commit message for the pushed files.} diff --git a/tests/testthat/test-compiler-ghpages.R b/tests/testthat/test-compiler-ghpages.R index 741497e2b..7fa9f4535 100644 --- a/tests/testthat/test-compiler-ghpages.R +++ b/tests/testthat/test-compiler-ghpages.R @@ -23,8 +23,22 @@ test_that("error for viz with no source", { }, "plot.list does not contain option named source, which is required by animint2pages") }) +## This test requires a fine-grained PAT +## - go to https://github.com/settings/personal-access-tokens/new +## - Resource owner: animint-test +## - Repository access: All repositories +## - Repository permissions: Administration and Contents: read and write. +## - Generate token +## - copy token and paste into PAT_GITHUB on https://github.com/animint/animint2/settings/secrets/actions +## Note that it is animint2pages_test_repo under owner=animint-test (not animint), because we want to limit the damage that a malicious user could do with this token: there are no repos with important data in the animint-test org. test_that("animint2pages() returns list of meta-data", { - result_list <- animint2pages(viz, github_repo = "animint2pages_test_repo") + ## https://docs.github.com/en/rest/repos/repos?apiVersion=2022-11-28#delete-a-repository says The fine-grained token must have the following permission set: "Administration" repository permissions (write) gh api --method DELETE -H "Accept: application/vnd.github+json" -H "X-GitHub-Api-Version: 2022-11-28" /repos/OWNER/REPO + gh::gh("DELETE /repos/animint-test/animint2pages_test_repo") + ## https://docs.github.com/en/rest/repos/repos?apiVersion=2022-11-28#create-an-organization-repository says The fine-grained token must have the following permission set: "Administration" repository permissions (write) + gh::gh("POST /orgs/animint-test/repos", name="animint2pages_test_repo") + ## first run of animint2pages creates new data viz. + result_list <- animint2pages(viz, "animint2pages_test_repo", owner="animint-test") + result_list expect_match(result_list$owner_repo, "animint2pages_test_repo") expect_match(result_list$viz_url, "github.io/animint2pages_test_repo") expect_match(result_list$gh_pages_url, "animint2pages_test_repo/tree/gh-pages") @@ -32,6 +46,18 @@ test_that("animint2pages() returns list of meta-data", { README.lines <- readLines(README.md) expected.line <- paste("##", viz$title) expect_identical(README.lines[1], expected.line) + get_tsv <- function(L)Sys.glob(file.path(L$local_clone, "*tsv")) + tsv_files_created <- get_tsv(result_list) + expect_equal(length(tsv_files_created), 1) + ## second run of animint2pages updates data viz. + viz.more <- viz + viz.more$five <- ggplot()+ + geom_point(aes( + x, x), + data=data.frame(x=1:5)) + update_list <- animint2pages(viz.more, "animint2pages_test_repo", owner="animint-test") + tsv_files_updated <- get_tsv(update_list) + expect_equal(length(tsv_files_updated), 2) }) test_that("animint2pages raises an error if no GitHub token is present", { From 811db7df20ff184dbcb319788001f14ae0717b4a Mon Sep 17 00:00:00 2001 From: Toby Dylan Hocking Date: Thu, 29 Aug 2024 12:51:51 -0400 Subject: [PATCH 3/5] apt install tidy --- .github/workflows/tests.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/tests.yaml b/.github/workflows/tests.yaml index cfe312bcb..b8e5b9ce9 100644 --- a/.github/workflows/tests.yaml +++ b/.github/workflows/tests.yaml @@ -23,7 +23,7 @@ jobs: - uses: actions/checkout@v3 - name: install and update texlive run: /usr/bin/sudo DEBIAN_FRONTEND=noninteractive apt update -y -qq - - run: /usr/bin/sudo DEBIAN_FRONTEND=noninteractive apt install texlive texlive-fonts-extra -y + - run: /usr/bin/sudo DEBIAN_FRONTEND=noninteractive apt install tidy texlive texlive-fonts-extra -y - uses: r-lib/actions/setup-r@v2 - uses: r-lib/actions/setup-r-dependencies@v2 From ffd702ecace5aa05e4acf7b01ad590146e895a47 Mon Sep 17 00:00:00 2001 From: Toby Dylan Hocking Date: Thu, 29 Aug 2024 16:18:57 -0400 Subject: [PATCH 4/5] LOCAL TESTING --- tests/testthat/test-compiler-ghpages.R | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/tests/testthat/test-compiler-ghpages.R b/tests/testthat/test-compiler-ghpages.R index 7fa9f4535..6d4fadfc3 100644 --- a/tests/testthat/test-compiler-ghpages.R +++ b/tests/testthat/test-compiler-ghpages.R @@ -23,7 +23,10 @@ test_that("error for viz with no source", { }, "plot.list does not contain option named source, which is required by animint2pages") }) -## This test requires a fine-grained PAT +## Running this test requires permission for creating and deleting repos under the animint-test org. +## GITHUB ACTIONS TESTING: +## In the context of github actions, we use a fine-grained PAT, +## Need to create one every year (1 year is the max expiration). ## - go to https://github.com/settings/personal-access-tokens/new ## - Resource owner: animint-test ## - Repository access: All repositories @@ -31,6 +34,14 @@ test_that("error for viz with no source", { ## - Generate token ## - copy token and paste into PAT_GITHUB on https://github.com/animint/animint2/settings/secrets/actions ## Note that it is animint2pages_test_repo under owner=animint-test (not animint), because we want to limit the damage that a malicious user could do with this token: there are no repos with important data in the animint-test org. +## LOCAL TESTING: +## First you need to become a member of the animint-test org (ask tdhock). +## On windows the credential manager will by default give you a token, +## without enough permissions to perform the delete operation. +## Use gitcreds::gitcreds_delete() if necessary to remove the old token. +## Go to https://github.com/settings/tokens/new and check repo and delete_repo, +## git bash on windows, git push, a window pops up, click token. +## Then the test case below should run locally. test_that("animint2pages() returns list of meta-data", { ## https://docs.github.com/en/rest/repos/repos?apiVersion=2022-11-28#delete-a-repository says The fine-grained token must have the following permission set: "Administration" repository permissions (write) gh api --method DELETE -H "Accept: application/vnd.github+json" -H "X-GitHub-Api-Version: 2022-11-28" /repos/OWNER/REPO gh::gh("DELETE /repos/animint-test/animint2pages_test_repo") From cffe8e47124df8c6fb1a032b729289a3843d1304 Mon Sep 17 00:00:00 2001 From: Toby Dylan Hocking Date: Fri, 30 Aug 2024 06:56:06 -0400 Subject: [PATCH 5/5] move docs to wiki --- tests/testthat/test-compiler-ghpages.R | 24 +++++------------------- 1 file changed, 5 insertions(+), 19 deletions(-) diff --git a/tests/testthat/test-compiler-ghpages.R b/tests/testthat/test-compiler-ghpages.R index 6d4fadfc3..049b6aa7b 100644 --- a/tests/testthat/test-compiler-ghpages.R +++ b/tests/testthat/test-compiler-ghpages.R @@ -23,25 +23,11 @@ test_that("error for viz with no source", { }, "plot.list does not contain option named source, which is required by animint2pages") }) -## Running this test requires permission for creating and deleting repos under the animint-test org. -## GITHUB ACTIONS TESTING: -## In the context of github actions, we use a fine-grained PAT, -## Need to create one every year (1 year is the max expiration). -## - go to https://github.com/settings/personal-access-tokens/new -## - Resource owner: animint-test -## - Repository access: All repositories -## - Repository permissions: Administration and Contents: read and write. -## - Generate token -## - copy token and paste into PAT_GITHUB on https://github.com/animint/animint2/settings/secrets/actions -## Note that it is animint2pages_test_repo under owner=animint-test (not animint), because we want to limit the damage that a malicious user could do with this token: there are no repos with important data in the animint-test org. -## LOCAL TESTING: -## First you need to become a member of the animint-test org (ask tdhock). -## On windows the credential manager will by default give you a token, -## without enough permissions to perform the delete operation. -## Use gitcreds::gitcreds_delete() if necessary to remove the old token. -## Go to https://github.com/settings/tokens/new and check repo and delete_repo, -## git bash on windows, git push, a window pops up, click token. -## Then the test case below should run locally. +## The test below requires a github token with repo delete +## permission. Read +## https://github.com/animint/animint2/wiki/Testing#installation to +## see how to set that up on your local computer, or on github +## actions. test_that("animint2pages() returns list of meta-data", { ## https://docs.github.com/en/rest/repos/repos?apiVersion=2022-11-28#delete-a-repository says The fine-grained token must have the following permission set: "Administration" repository permissions (write) gh api --method DELETE -H "Accept: application/vnd.github+json" -H "X-GitHub-Api-Version: 2022-11-28" /repos/OWNER/REPO gh::gh("DELETE /repos/animint-test/animint2pages_test_repo")